X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fmodules%2Fonefs_open.c;h=a77d6f3e7e7cc37db4401ef4715d3aa26495de7e;hb=bfe4a2baeec6bc4558a617ec67532ea11f865861;hp=60a1790f642850682f5d78af95c1b9c17036b5d4;hpb=1a1d10d22f7a2eebd22e76614c3c74b4d49e5c33;p=samba.git diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c index 60a1790f642..a77d6f3e7e7 100644 --- a/source3/modules/onefs_open.c +++ b/source3/modules/onefs_open.c @@ -33,6 +33,7 @@ */ #include "includes.h" +#include "smbd/smbd.h" #include "onefs.h" #include "onefs_config.h" #include "oplock_onefs.h" @@ -54,6 +55,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, uint32_t file_attributes, uint32_t oplock_request, uint64_t allocation_size, + uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, @@ -81,7 +83,6 @@ static NTSTATUS onefs_open_file(files_struct *fsp, struct security_descriptor *sd, int *granted_oplock) { - char *path = NULL; struct smb_filename *smb_fname_onefs = NULL; NTSTATUS status = NT_STATUS_OK; int accmode = (flags & O_ACCMODE); @@ -93,12 +94,6 @@ static NTSTATUS onefs_open_file(files_struct *fsp, fsp->fh->fd = -1; errno = EPERM; - status = get_full_smb_filename(talloc_tos(), smb_fname, - &path); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* Check permissions */ /* @@ -163,9 +158,9 @@ static NTSTATUS onefs_open_file(files_struct *fsp, * wildcard characters are allowed in stream names * only test the basefilename */ - wild = fsp->base_fsp->fsp_name; + wild = fsp->base_fsp->fsp_name->base_name; } else { - wild = path; + wild = smb_fname->base_name; } if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(wild)) { @@ -257,8 +252,8 @@ static NTSTATUS onefs_open_file(files_struct *fsp, /* Inherit the ACL if required */ if (lp_inherit_perms(SNUM(conn))) { - inherit_access_posix_acl(conn, parent_dir, path, - unx_mode); + inherit_access_posix_acl(conn, parent_dir, + smb_fname->base_name, unx_mode); } /* Change the owner if required. */ @@ -268,7 +263,7 @@ static NTSTATUS onefs_open_file(files_struct *fsp, } notify_fname(conn, NOTIFY_ACTION_ADDED, - FILE_NOTIFY_CHANGE_FILE_NAME, path); + FILE_NOTIFY_CHANGE_FILE_NAME, smb_fname->base_name); } if (!file_existed) { @@ -319,21 +314,21 @@ static NTSTATUS onefs_open_file(files_struct *fsp, fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; } - fsp->print_file = False; + fsp->print_file = NULL; fsp->modified = False; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; if (conn->aio_write_behind_list && - is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) { + is_in_path(smb_fname->base_name, conn->aio_write_behind_list, + conn->case_sensitive)) { fsp->aio_write_behind = True; } - string_set(&fsp->fsp_name, path); fsp->wcp = NULL; /* Write cache pointer. */ DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n", - conn->server_info->unix_name, - fsp->fsp_name, + conn->session_info->unix_info->unix_name, + smb_fname_str_dbg(smb_fname), BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write), conn->num_files_open)); @@ -364,7 +359,8 @@ static void defer_open(struct share_mode_lock *lck, if (procid_is_me(&e->pid) && (e->op_mid == req->mid)) { DEBUG(0, ("Trying to defer an already deferred " - "request: mid=%d, exiting\n", req->mid)); + "request: mid=%llu, exiting\n", + (unsigned long long)req->mid)); exit_server("attempt to defer a deferred request"); } } @@ -372,14 +368,14 @@ static void defer_open(struct share_mode_lock *lck, /* End paranoia check */ DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " - "open entry for mid %u\n", + "open entry for mid %llu\n", (unsigned int)request_time.tv_sec, (unsigned int)request_time.tv_usec, - (unsigned int)req->mid)); + (unsigned long long)req->mid)); - if (!push_deferred_smb_message(req, request_time, timeout, - (char *)state, sizeof(*state))) { - exit_server("push_deferred_smb_message failed"); + if (!push_deferred_open_message_smb(req, request_time, timeout, + state->id, (char *)state, sizeof(*state))) { + exit_server("push_deferred_open_message_smb failed"); } add_deferred_open(lck, req->mid, request_time, state->id); } @@ -423,6 +419,13 @@ static void schedule_defer_open(struct share_mode_lock *lck, if (!request_timed_out(request_time, timeout)) { defer_open(lck, request_time, timeout, req, &state); + } else { + /* A delayed-for-oplocks deferred open timing out should only + * happen if there is a bug or extreme load, since we set the + * timeout to 300 seconds. */ + DEBUG(0, ("Deferred open timeout! request_time=%d.%d, " + "mid=%d\n", request_time.tv_sec, request_time.tv_usec, + req->mid)); } } @@ -438,6 +441,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, uint32 create_options, uint32 new_dos_attributes, int oplock_request, + uint32_t private_flags, struct security_descriptor *sd, files_struct *fsp, int *pinfo, @@ -455,7 +459,6 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, mode_t unx_mode = (mode_t)0; int info; uint32 existing_dos_attributes = 0; - struct pending_message_list *pml = NULL; struct timeval request_time = timeval_zero(); struct share_mode_lock *lck = NULL; uint32 open_access_mask = access_mask; @@ -465,16 +468,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, int granted_oplock; uint64_t oplock_callback_id = 0; uint32 createfile_attributes = 0; - char *fname = NULL; ZERO_STRUCT(id); - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (conn->printer) { /* * Printers are handled completely differently. @@ -488,8 +484,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("onefs_open_file_ntcreate: printer open fname=%s\n", smb_fname_str_dbg(smb_fname))); - return print_fsp_open(req, conn, fname, req->vuid, fsp, - &smb_fname->st); + return print_spool_open(fsp, smb_fname->base_name, + req->vuid); } if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir, @@ -502,9 +498,9 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS); new_dos_attributes = 0; } else { - /* We add aARCH to this as this mode is only used if the file is + /* We add FILE_ATTRIBUTE_ARCHIVE to this as this mode is only used if the file is * created new. */ - unx_mode = unix_mode(conn, new_dos_attributes | aARCH, + unx_mode = unix_mode(conn, new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE, smb_fname, parent_dir); } @@ -547,39 +543,33 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * Only non-internal opens can be deferred at all */ - if ((req != NULL) - && ((pml = get_open_deferred_message(req->mid)) != NULL)) { - struct deferred_open_record *state = - (struct deferred_open_record *)pml->private_data.data; + if (req) { + void *ptr; + if (get_deferred_open_message_state(req, + &request_time, + &ptr)) { + struct deferred_open_record *state = (struct deferred_open_record *)ptr; - /* Remember the absolute time of the original - request with this mid. We'll use it later to - see if this has timed out. */ + /* Remember the absolute time of the original + request with this mid. We'll use it later to + see if this has timed out. */ - request_time = pml->request_time; + /* Remove the deferred open entry under lock. */ + remove_deferred_open_entry(state->id, req->mid); - /* Remove the deferred open entry under lock. */ - lck = get_share_mode_lock(talloc_tos(), state->id, NULL, NULL, - NULL); - if (lck == NULL) { - DEBUG(0, ("could not get share mode lock\n")); - } else { - del_deferred_open_entry(lck, req->mid); - TALLOC_FREE(lck); - } + /* Ensure we don't reprocess this message. */ + remove_deferred_open_message_smb(req->mid); - /* Ensure we don't reprocess this message. */ - remove_deferred_open_smb_message(req->mid); - - /* - * When receiving a semlock_async_failure message, the - * deferred open will be marked as "failed". Returning - * INTERNAL_ERROR. - */ - if (state->failed) { - DEBUG(0, ("onefs_open_file_ntcreate: " - "semlock_async_failure detected!\n")); - return NT_STATUS_INTERNAL_ERROR; + /* + * When receiving a semlock_async_failure message, the + * deferred open will be marked as "failed". Returning + * INTERNAL_ERROR. + */ + if (state->failed) { + DEBUG(0, ("onefs_open_file_ntcreate: " + "semlock_async_failure detected!\n")); + return NT_STATUS_INTERNAL_ERROR; + } } } @@ -597,12 +587,12 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, /* Setup dos_attributes to be set by ifs_createfile */ if (lp_store_dos_attributes(SNUM(conn))) { - createfile_attributes = (new_dos_attributes | aARCH) & + createfile_attributes = (new_dos_attributes | FILE_ATTRIBUTE_ARCHIVE) & ~(FILE_ATTRIBUTE_NONINDEXED | FILE_ATTRIBUTE_COMPRESSED); } /* Ignore oplock requests if oplocks are disabled. */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || + if (!lp_oplocks(SNUM(conn)) || IS_VETO_OPLOCK_PATH(conn, smb_fname->base_name)) { /* Mask off everything except the private Samba bits. */ oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK; @@ -824,9 +814,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, DEBUG(10, ("fsp = %p\n", fsp)); - fsp->file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st); fsp->share_access = share_access; - fsp->fh->private_options = create_options; + fsp->fh->private_options = private_flags; fsp->access_mask = open_access_mask; /* We change this to the * requested access_mask after * the open is done. */ @@ -845,7 +834,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("Could not get share mode lock\n")); @@ -882,7 +871,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, */ if (req) { SMB_ASSERT(fsp_data); - oplock_callback_id = onefs_oplock_wait_record(req->mid); + oplock_callback_id = onefs_oplock_wait_record(req->sconn, + req->mid); if (oplock_callback_id == 0) { return NT_STATUS_NO_MEMORY; } @@ -892,6 +882,12 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * stat-only open at this point. */ SMB_ASSERT(fsp->oplock_type == NO_OPLOCK); + + /* The kernel and Samba's version of stat-only differs + * slightly: The kernel doesn't think its stat-only if we're + * truncating. We'd better have a req in order to defer the + * open. */ + SMB_ASSERT(!((flags|flags2) & O_TRUNC)); } /* Do the open. */ @@ -917,13 +913,22 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, /* OneFS Oplock Handling */ if (errno == EINPROGRESS) { + /* If we get EINPROGRESS, the kernel will send us an + * asynchronous semlock event back. Ensure we can defer + * the open, by asserting req. */ + SMB_ASSERT(req); + if (lck == NULL) { + /* + * We hit the race that when we did the stat + * on the file it did not exist, and someone + * has created it in between the stat and the + * open_file() call. Defer our open waiting, + * to break the oplock of the first opener. + */ - struct deferred_open_record state; struct timespec old_write_time; - old_write_time = smb_fname->st.st_ex_mtime; - DEBUG(3, ("Someone created file %s with an " "oplock after we looked: Retrying\n", smb_fname_str_dbg(smb_fname))); @@ -936,7 +941,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, id = vfs_file_id_from_sbuf(conn, &smb_fname->st); if (!(lck = get_share_mode_lock(talloc_tos(), - id, conn->connectpath, fname, + id, conn->connectpath, smb_fname, &old_write_time))) { /* * Emergency exit @@ -946,17 +951,15 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, "lock for %s\n", smb_fname_str_dbg(smb_fname))); status = NT_STATUS_SHARING_VIOLATION; + + /* XXXZLK: This will cause us to get a + * semlock event when we aren't + * expecting one. */ goto cleanup_destroy; } - state.delayed_for_oplocks = False; - state.id = id; - - if (req != NULL) { - defer_open(lck, request_time, - timeval_zero(), req, &state); - } - goto cleanup_destroy; + schedule_defer_open(lck, request_time, req); + goto cleanup; } /* Waiting for an oplock */ DEBUG(5,("Async createfile because a client has an " @@ -973,11 +976,21 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, uint32 can_access_mask; bool can_access = True; + /* If we raced on open we may not have a valid file_id + * or stat buf. Get them again. */ + if (SMB_VFS_STAT(conn, fname, psbuf) == -1) { + DEBUG(0,("Error doing stat on file %s " + "(%s)\n", fname, strerror(errno))); + status = NT_STATUS_SHARING_VIOLATION; + goto cleanup_destroy; + } + id = vfs_file_id_from_sbuf(conn, psbuf); + /* Check if this can be done with the deny_dos and fcb * calls. */ /* Try to find dup fsp if possible. */ - if (create_options & + if (private_flags & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { @@ -993,7 +1006,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, status = fcb_or_dos_open(req, conn, fsp, - fname, + smb_fname, id, req->smbpid, req->vuid, @@ -1030,8 +1043,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) || - !can_access_file_data(conn, smb_fname, - can_access_mask)) { + !NT_STATUS_IS_OK(smbd_check_access_rights(conn, + smb_fname, can_access_mask))) { can_access = False; } @@ -1073,9 +1086,39 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, state.id = id; state.failed = false; - if ((req != NULL) - && !request_timed_out(request_time, - timeout)) { + /* + * We hit the race that when we did the stat + * on the file it did not exist, and someone + * has created it in between the stat and the + * open_file() call. Retrieve the share_mode + * lock on the newly opened file so we can + * defer our request. + */ + if (lck == NULL) { + struct timespec old_write_time; + old_write_time = get_mtimespec(psbuf); + + lck = get_share_mode_lock(talloc_tos(), + id, conn->connectpath, fname, + &old_write_time); + if (lck == NULL) { + DEBUG(0, + ("onefs_open_file_ntcreate:" + " Could not get share " + "mode lock for %s\n", + fname)); + /* This will cause us to return + * immediately skipping the + * the 1 second delay, which + * isn't a big deal */ + status = NT_STATUS_SHARING_VIOLATION; + goto cleanup_destroy; + } + } + + if ((req != NULL) && + !request_timed_out(request_time, timeout)) + { defer_open(lck, request_time, timeout, req, &state); } @@ -1127,8 +1170,8 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, /* * Now the file exists and fsp is successfully opened, - * fsp->dev and fsp->inode are valid and should replace the - * dev=0,inode=0 from a non existent file. Spotted by + * fsp->file_id is valid and should replace the + * dev=0, inode=0 from a non existent file. Spotted by * Nadav Danieli . JRA. */ @@ -1136,7 +1179,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, lck = get_share_mode_lock(talloc_tos(), id, conn->connectpath, - fname, &old_write_time); + smb_fname, &old_write_time); if (lck == NULL) { DEBUG(0, ("onefs_open_file_ntcreate: Could not get " @@ -1201,7 +1244,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, note that GPFS supports it as well - jmcd */ if (fsp->fh->fd != -1) { - ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access); + ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, share_access, access_mask); if(ret_flock == -1 ){ TALLOC_FREE(lck); @@ -1216,9 +1259,6 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, * deny mode is compatible with all current opens. */ - /* Record the options we were opened with. */ - fsp->share_access = share_access; - fsp->fh->private_options = create_options; /* * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted, */ @@ -1271,12 +1311,13 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn, new_file_created = True; } - set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, + set_share_mode(lck, fsp, get_current_uid(conn), + req ? req->mid : 0, fsp->oplock_type); /* Handle strange delete on close create semantics. */ if (create_options & FILE_DELETE_ON_CLOSE) { - status = can_set_delete_on_close(fsp, True, new_dos_attributes); + status = can_set_delete_on_close(fsp, new_dos_attributes); if (!NT_STATUS_IS_OK(status)) { /* Remember to delete the mode we just added. */ @@ -1443,7 +1484,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS); file_attributes = 0; } else { - mode = unix_mode(conn, aDIR, smb_dname, parent_dir); + mode = unix_mode(conn, FILE_ATTRIBUTE_DIRECTORY, smb_dname, parent_dir); } /* @@ -1584,19 +1625,24 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, fsp->can_write = False; fsp->share_access = share_access; - fsp->fh->private_options = create_options; + fsp->fh->private_options = 0; /* * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted, */ fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES; - fsp->print_file = False; + fsp->print_file = NULL; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = True; fsp->posix_open = posix_open; - string_set(&fsp->fsp_name, smb_dname->base_name); + status = fsp_set_smb_fname(fsp, smb_dname); + if (!NT_STATUS_IS_OK(status)) { + fd_close(fsp); + file_free(req, fsp); + return status; + } mtimespec = smb_dname->st.st_ex_mtime; @@ -1605,8 +1651,7 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, * semantics and to make smbstatus more useful. */ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, - conn->connectpath, smb_dname->base_name, - &mtimespec); + conn->connectpath, smb_dname, &mtimespec); if (lck == NULL) { DEBUG(0, ("onefs_open_directory: Could not get share mode " @@ -1623,14 +1668,15 @@ static NTSTATUS onefs_open_directory(connection_struct *conn, return NT_STATUS_DELETE_PENDING; } - set_share_mode(lck, fsp, conn->server_info->utok.uid, 0, NO_OPLOCK); + set_share_mode(lck, fsp, get_current_uid(conn), + req ? req->mid : 0, NO_OPLOCK); /* * For directories the delete on close bit at open time seems * always to be honored on close... See test 19 in Samba4 BASE-DELETE. */ if (create_options & FILE_DELETE_ON_CLOSE) { - status = can_set_delete_on_close(fsp, True, 0); + status = can_set_delete_on_close(fsp, 0); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) { TALLOC_FREE(lck); @@ -1669,6 +1715,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, uint32_t file_attributes, uint32_t oplock_request, uint64_t allocation_size, + uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, @@ -1683,7 +1730,8 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, DEBUG(10,("onefs_create_file_unixpath: access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " - "oplock_request = 0x%x ea_list = 0x%p, sd = 0x%p, " + "oplock_request = 0x%x private_flags = 0x%x " + "ea_list = 0x%p, sd = 0x%p, " "fname = %s\n", (unsigned int)access_mask, (unsigned int)file_attributes, @@ -1691,6 +1739,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)create_options, (unsigned int)oplock_request, + (unsigned int)private_flags, ea_list, sd, smb_fname_str_dbg(smb_fname))); if (create_options & FILE_OPEN_BY_FILE_ID) { @@ -1774,6 +1823,7 @@ static NTSTATUS onefs_create_file_unixpath(connection_struct *conn, file_attributes, /* file_attributes */ NO_OPLOCK, /* oplock_request */ 0, /* allocation_size */ + 0, /* private_flags */ NULL, /* sd */ NULL, /* ea_list */ &base_fsp, /* result */ @@ -2017,6 +2067,7 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, uint32_t file_attributes, uint32_t oplock_request, uint64_t allocation_size, + uint32_t private_flags, struct security_descriptor *sd, struct ea_list *ea_list, files_struct **result, @@ -2031,7 +2082,7 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, DEBUG(10,("onefs_create_file: access_mask = 0x%x " "file_attributes = 0x%x, share_access = 0x%x, " "create_disposition = 0x%x create_options = 0x%x " - "oplock_request = 0x%x " + "oplock_request = 0x%x private_flags = 0x%x" "root_dir_fid = 0x%x, ea_list = 0x%p, sd = 0x%p, " "fname = %s\n", (unsigned int)access_mask, @@ -2040,16 +2091,19 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, (unsigned int)create_disposition, (unsigned int)create_options, (unsigned int)oplock_request, + (unsigned int)private_flags, (unsigned int)root_dir_fid, ea_list, sd, smb_fname_str_dbg(smb_fname))); /* Get the file name if root_dir_fid was specified. */ if (root_dir_fid != 0) { + struct smb_filename *smb_fname_out = NULL; status = get_relative_fid_filename(conn, req, root_dir_fid, - smb_fname); + smb_fname, &smb_fname_out); if (!NT_STATUS_IS_OK(status)) { goto fail; } + smb_fname = smb_fname_out; } /* All file access must go through check_name() */ @@ -2058,6 +2112,33 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, goto fail; } + if (is_ntfs_stream_smb_fname(smb_fname)) { + if (!(conn->fs_capabilities & FILE_NAMED_STREAMS)) { + status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto fail; + } + + if (is_ntfs_default_stream_smb_fname(smb_fname)) { + int ret; + smb_fname->stream_name = NULL; + /* We have to handle this error here. */ + if (create_options & FILE_DIRECTORY_FILE) { + status = NT_STATUS_NOT_A_DIRECTORY; + goto fail; + } + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(conn, smb_fname); + } else { + ret = SMB_VFS_STAT(conn, smb_fname); + } + + if (ret == 0 && VALID_STAT_OF_DIR(smb_fname->st)) { + status = NT_STATUS_FILE_IS_A_DIRECTORY; + goto fail; + } + } + } + status = onefs_create_file_unixpath( conn, /* conn */ req, /* req */ @@ -2069,6 +2150,7 @@ NTSTATUS onefs_create_file(vfs_handle_struct *handle, file_attributes, /* file_attributes */ oplock_request, /* oplock_request */ allocation_size, /* allocation_size */ + private_flags, sd, /* sd */ ea_list, /* ea_list */ &fsp, /* result */