static NTSTATUS fruit_check_access(vfs_handle_struct *handle,
files_struct *fsp,
uint32_t access_mask,
- uint32_t deny_mode)
+ uint32_t share_mode)
{
NTSTATUS status = NT_STATUS_OK;
- bool open_for_reading, open_for_writing, deny_read, deny_write;
off_t off;
- bool have_read = false;
- int flags;
+ bool share_for_read = (share_mode & FILE_SHARE_READ);
+ bool share_for_write = (share_mode & FILE_SHARE_WRITE);
+ bool netatalk_already_open_for_reading = false;
+ bool netatalk_already_open_for_writing = false;
+ bool netatalk_already_open_with_deny_read = false;
+ bool netatalk_already_open_with_deny_write = false;
/* FIXME: hardcoded data fork, add resource fork */
enum apple_fork fork_type = APPLE_FORK_DATA;
- DEBUG(10, ("fruit_check_access: %s, am: %s/%s, dm: %s/%s\n",
+ DBG_DEBUG("fruit_check_access: %s, am: %s/%s, sm: 0x%x\n",
fsp_str_dbg(fsp),
access_mask & FILE_READ_DATA ? "READ" :"-",
access_mask & FILE_WRITE_DATA ? "WRITE" : "-",
- deny_mode & DENY_READ ? "DENY_READ" : "-",
- deny_mode & DENY_WRITE ? "DENY_WRITE" : "-"));
+ share_mode);
if (fsp->fh->fd == -1) {
return NT_STATUS_OK;
}
- flags = fcntl(fsp->fh->fd, F_GETFL);
- if (flags == -1) {
- DBG_ERR("fcntl get flags [%s] fd [%d] failed [%s]\n",
- fsp_str_dbg(fsp), fsp->fh->fd, strerror(errno));
- return map_nt_error_from_unix(errno);
- }
-
- if (flags & (O_RDONLY|O_RDWR)) {
- /*
- * Applying fcntl read locks requires an fd opened for
- * reading. This means we won't be applying locks for
- * files openend write-only, but what can we do...
- */
- have_read = true;
- }
+ /* Read NetATalk opens and deny modes on the file. */
+ netatalk_already_open_for_reading = test_netatalk_lock(fsp,
+ access_to_netatalk_brl(fork_type,
+ FILE_READ_DATA));
- /*
- * Check read access and deny read mode
- */
- if ((access_mask & FILE_READ_DATA) || (deny_mode & DENY_READ)) {
- /* Check access */
- open_for_reading = test_netatalk_lock(
- fsp, access_to_netatalk_brl(fork_type, FILE_READ_DATA));
+ netatalk_already_open_with_deny_read = test_netatalk_lock(fsp,
+ denymode_to_netatalk_brl(fork_type,
+ DENY_READ));
- deny_read = test_netatalk_lock(
- fsp, denymode_to_netatalk_brl(fork_type, DENY_READ));
+ netatalk_already_open_for_writing = test_netatalk_lock(fsp,
+ access_to_netatalk_brl(fork_type,
+ FILE_WRITE_DATA));
- DEBUG(10, ("read: %s, deny_write: %s\n",
- open_for_reading == true ? "yes" : "no",
- deny_read == true ? "yes" : "no"));
+ netatalk_already_open_with_deny_write = test_netatalk_lock(fsp,
+ denymode_to_netatalk_brl(fork_type,
+ DENY_WRITE));
- if (((access_mask & FILE_READ_DATA) && deny_read)
- || ((deny_mode & DENY_READ) && open_for_reading)) {
- return NT_STATUS_SHARING_VIOLATION;
- }
+ /* If there are any conflicts - sharing violation. */
+ if ((access_mask & FILE_READ_DATA) &&
+ netatalk_already_open_with_deny_read) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- /* Set locks */
- if ((access_mask & FILE_READ_DATA) && have_read) {
- struct byte_range_lock *br_lck = NULL;
+ if (!share_for_read &&
+ netatalk_already_open_for_reading) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- off = access_to_netatalk_brl(fork_type, FILE_READ_DATA);
- br_lck = do_lock(
- handle->conn->sconn->msg_ctx, fsp,
- fsp->op->global->open_persistent_id, 1, off,
- READ_LOCK, POSIX_LOCK, false,
- &status, NULL);
+ if ((access_mask & FILE_WRITE_DATA) &&
+ netatalk_already_open_with_deny_write) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- TALLOC_FREE(br_lck);
+ if (!share_for_write &&
+ netatalk_already_open_for_writing) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
+ if (!(access_mask & FILE_READ_DATA)) {
+ /*
+ * Nothing we can do here, we need read access
+ * to set locks.
+ */
+ return NT_STATUS_OK;
+ }
- if ((deny_mode & DENY_READ) && have_read) {
- struct byte_range_lock *br_lck = NULL;
+ /* Set NetAtalk locks matching our access */
+ if (access_mask & FILE_READ_DATA) {
+ struct byte_range_lock *br_lck = NULL;
- off = denymode_to_netatalk_brl(fork_type, DENY_READ);
- br_lck = do_lock(
- handle->conn->sconn->msg_ctx, fsp,
- fsp->op->global->open_persistent_id, 1, off,
- READ_LOCK, POSIX_LOCK, false,
- &status, NULL);
+ off = access_to_netatalk_brl(fork_type, FILE_READ_DATA);
+ br_lck = do_lock(
+ handle->conn->sconn->msg_ctx, fsp,
+ fsp->op->global->open_persistent_id, 1, off,
+ READ_LOCK, POSIX_LOCK, false,
+ &status, NULL);
- TALLOC_FREE(br_lck);
+ TALLOC_FREE(br_lck);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
}
- /*
- * Check write access and deny write mode
- */
- if ((access_mask & FILE_WRITE_DATA) || (deny_mode & DENY_WRITE)) {
- /* Check access */
- open_for_writing = test_netatalk_lock(
- fsp, access_to_netatalk_brl(fork_type, FILE_WRITE_DATA));
+ if (!share_for_read) {
+ struct byte_range_lock *br_lck = NULL;
- deny_write = test_netatalk_lock(
- fsp, denymode_to_netatalk_brl(fork_type, DENY_WRITE));
+ off = denymode_to_netatalk_brl(fork_type, DENY_READ);
+ br_lck = do_lock(
+ handle->conn->sconn->msg_ctx, fsp,
+ fsp->op->global->open_persistent_id, 1, off,
+ READ_LOCK, POSIX_LOCK, false,
+ &status, NULL);
- DEBUG(10, ("write: %s, deny_write: %s\n",
- open_for_writing == true ? "yes" : "no",
- deny_write == true ? "yes" : "no"));
+ TALLOC_FREE(br_lck);
- if (((access_mask & FILE_WRITE_DATA) && deny_write)
- || ((deny_mode & DENY_WRITE) && open_for_writing)) {
- return NT_STATUS_SHARING_VIOLATION;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+ }
- /* Set locks */
- if ((access_mask & FILE_WRITE_DATA) && have_read) {
- struct byte_range_lock *br_lck = NULL;
+ if (access_mask & FILE_WRITE_DATA) {
+ struct byte_range_lock *br_lck = NULL;
- off = access_to_netatalk_brl(fork_type, FILE_WRITE_DATA);
- br_lck = do_lock(
- handle->conn->sconn->msg_ctx, fsp,
- fsp->op->global->open_persistent_id, 1, off,
- READ_LOCK, POSIX_LOCK, false,
- &status, NULL);
+ off = access_to_netatalk_brl(fork_type, FILE_WRITE_DATA);
+ br_lck = do_lock(
+ handle->conn->sconn->msg_ctx, fsp,
+ fsp->op->global->open_persistent_id, 1, off,
+ READ_LOCK, POSIX_LOCK, false,
+ &status, NULL);
- TALLOC_FREE(br_lck);
+ TALLOC_FREE(br_lck);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
- if ((deny_mode & DENY_WRITE) && have_read) {
- struct byte_range_lock *br_lck = NULL;
+ }
- off = denymode_to_netatalk_brl(fork_type, DENY_WRITE);
- br_lck = do_lock(
- handle->conn->sconn->msg_ctx, fsp,
- fsp->op->global->open_persistent_id, 1, off,
- READ_LOCK, POSIX_LOCK, false,
- &status, NULL);
+ if (!share_for_write) {
+ struct byte_range_lock *br_lck = NULL;
- TALLOC_FREE(br_lck);
+ off = denymode_to_netatalk_brl(fork_type, DENY_WRITE);
+ br_lck = do_lock(
+ handle->conn->sconn->msg_ctx, fsp,
+ fsp->op->global->open_persistent_id, 1, off,
+ READ_LOCK, POSIX_LOCK, false,
+ &status, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ TALLOC_FREE(br_lck);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
}
- return status;
+ return NT_STATUS_OK;
}
static NTSTATUS check_aapl(vfs_handle_struct *handle,
status = fruit_check_access(
handle, *result,
access_mask,
- map_share_mode_to_deny_mode(share_access, 0));
+ share_access);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}