X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fsmbd%2Freply.c;h=955ebdd7829b11639e4d9b0fa06f4ab5118ff7d3;hb=21b380ca133417df096e2b262a5da41faff186ea;hp=6e576552fcd83099b463ad04dbc56a29d4cc4ebd;hpb=ca8afc660474bad2327300bc19d3b01e617f171b;p=gd%2Fsamba-autobuild%2F.git diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6e576552fcd..955ebdd7829 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1625,38 +1625,6 @@ void reply_dskattr(struct smb_request *req) return; } -/* - * Utility function to split the filename from the directory. - */ -static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in, - char **fname_dir_out, - char **fname_mask_out) -{ - const char *p = NULL; - char *fname_dir = NULL; - char *fname_mask = NULL; - - p = strrchr_m(fname_in, '/'); - if (!p) { - fname_dir = talloc_strdup(ctx, "."); - fname_mask = talloc_strdup(ctx, fname_in); - } else { - fname_dir = talloc_strndup(ctx, fname_in, - PTR_DIFF(p, fname_in)); - fname_mask = talloc_strdup(ctx, p+1); - } - - if (!fname_dir || !fname_mask) { - TALLOC_FREE(fname_dir); - TALLOC_FREE(fname_mask); - return NT_STATUS_NO_MEMORY; - } - - *fname_dir_out = fname_dir; - *fname_mask_out = fname_mask; - return NT_STATUS_OK; -} - /**************************************************************************** Make a dir struct. ****************************************************************************/ @@ -1780,15 +1748,17 @@ void reply_search(struct smb_request *req) /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */ if (status_len == 0) { - int ret; + const char *dirpath; struct smb_filename *smb_dname = NULL; - uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); - nt_status = filename_convert(ctx, conn, - path, - ucf_flags, - 0, - &smb_fname); + uint32_t ucf_flags = ucf_flags_from_smb_request(req); + + nt_status = filename_convert_smb1_search_path(ctx, + conn, + path, + ucf_flags, + &smb_dname, + &mask); + if (!NT_STATUS_IS_OK(nt_status)) { if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) { reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, @@ -1799,56 +1769,9 @@ void reply_search(struct smb_request *req) goto out; } - directory = smb_fname->base_name; - - p = strrchr_m(directory,'/'); - if ((p != NULL) && (*directory != '/')) { - mask = talloc_strdup(ctx, p + 1); - directory = talloc_strndup(ctx, directory, - PTR_DIFF(p, directory)); - } else { - mask = talloc_strdup(ctx, directory); - directory = talloc_strdup(ctx,"."); - } - - if (!directory) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); - smb_dname = synthetic_smb_fname(talloc_tos(), - directory, - NULL, - NULL, - smb_fname->twrp, - smb_fname->flags); - if (smb_dname == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - /* - * As we've cut off the last component from - * smb_fname we need to re-stat smb_dname - * so FILE_OPEN disposition knows the directory - * exists. - */ - ret = vfs_stat(conn, smb_dname); - if (ret == -1) { - nt_status = map_nt_error_from_unix(errno); - reply_nterror(req, nt_status); - goto out; - } - - nt_status = openat_pathref_fsp(conn->cwd_fsp, smb_dname); - if (!NT_STATUS_IS_OK(nt_status)) { - reply_nterror(req, nt_status); - goto out; - } - /* * Open an fsp on this directory for the dptr. */ @@ -1898,13 +1821,18 @@ void reply_search(struct smb_request *req) * as this is not a client visible handle so * can'tbe part of an SMB1 chain. */ - close_file(NULL, fsp, NORMAL_CLOSE); - fsp = NULL; + close_file_free(NULL, &fsp, NORMAL_CLOSE); reply_nterror(req, nt_status); goto out; } dptr_num = dptr_dnum(fsp->dptr); + dirpath = dptr_path(sconn, dptr_num); + directory = talloc_strdup(ctx, dirpath); + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + goto out; + } } else { int status_dirtype; @@ -2024,15 +1952,13 @@ void reply_search(struct smb_request *req) if (numentries == 0) { dptr_num = -1; if (fsp != NULL) { - close_file(NULL, fsp, NORMAL_CLOSE); - fsp = NULL; + close_file_free(NULL, &fsp, NORMAL_CLOSE); } } else if(expect_close && status_len == 0) { /* Close the dptr - we know it's gone */ dptr_num = -1; if (fsp != NULL) { - close_file(NULL, fsp, NORMAL_CLOSE); - fsp = NULL; + close_file_free(NULL, &fsp, NORMAL_CLOSE); } } @@ -2041,8 +1967,7 @@ void reply_search(struct smb_request *req) dptr_num = -1; /* fsp may have been closed above. */ if (fsp != NULL) { - close_file(NULL, fsp, NORMAL_CLOSE); - fsp = NULL; + close_file_free(NULL, &fsp, NORMAL_CLOSE); } } @@ -2144,8 +2069,7 @@ void reply_fclose(struct smb_request *req) fsp = dptr_fetch_fsp(sconn, status+12,&dptr_num); if(fsp != NULL) { /* Close the file - we know it's gone */ - close_file(NULL, fsp, NORMAL_CLOSE); - fsp = NULL; + close_file_free(NULL, &fsp, NORMAL_CLOSE); dptr_num = -1; } @@ -2287,7 +2211,7 @@ void reply_open(struct smb_request *req) if (fattr & FILE_ATTRIBUTE_DIRECTORY) { DEBUG(3,("attempt to open a directory %s\n", fsp_str_dbg(fsp))); - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_botherror(req, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess); goto out; @@ -2472,19 +2396,19 @@ void reply_open_and_X(struct smb_request *req) if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_DISK_FULL); goto out; } retval = vfs_set_filelen(fsp, (off_t)allocation_size); if (retval < 0) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_DISK_FULL); goto out; } status = vfs_stat_fsp(fsp); if (!NT_STATUS_IS_OK(status)) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, status); goto out; } @@ -2492,7 +2416,7 @@ void reply_open_and_X(struct smb_request *req) fattr = fdos_mode(fsp); if (fattr & FILE_ATTRIBUTE_DIRECTORY) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; } @@ -3131,10 +3055,10 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp, * unlink a file with all relevant access checks *******************************************************************/ -static NTSTATUS do_unlink(connection_struct *conn, +NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req, - struct smb_filename *smb_fname, - uint32_t dirtype) + uint32_t dirtype, + struct smb_filename *smb_fname) { uint32_t fattr; files_struct *fsp; @@ -3143,9 +3067,13 @@ static NTSTATUS do_unlink(connection_struct *conn, int ret; struct smb2_create_blobs *posx = NULL; - DEBUG(10,("do_unlink: %s, dirtype = %d\n", + if (dirtype == 0) { + dirtype = FILE_ATTRIBUTE_NORMAL; + } + + DBG_DEBUG("%s, dirtype = %d\n", smb_fname_str_dbg(smb_fname), - dirtype)); + dirtype); if (!CAN_WRITE(conn)) { return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -3245,18 +3173,18 @@ static NTSTATUS do_unlink(connection_struct *conn, TALLOC_FREE(posx); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n", - nt_errstr(status))); + DBG_DEBUG("SMB_VFS_CREATEFILE failed: %s\n", + nt_errstr(status)); return status; } status = can_set_delete_on_close(fsp, fattr); if (!NT_STATUS_IS_OK(status)) { - DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - " + DBG_DEBUG("can_set_delete_on_close for file %s - " "(%s)\n", smb_fname_str_dbg(smb_fname), - nt_errstr(status))); - close_file(req, fsp, NORMAL_CLOSE); + nt_errstr(status)); + close_file_free(req, &fsp, NORMAL_CLOSE); return status; } @@ -3264,267 +3192,11 @@ static NTSTATUS do_unlink(connection_struct *conn, if (!set_delete_on_close(fsp, True, conn->session_info->security_token, conn->session_info->unix_token)) { - close_file(req, fsp, NORMAL_CLOSE); + close_file_free(req, &fsp, NORMAL_CLOSE); return NT_STATUS_ACCESS_DENIED; } - return close_file(req, fsp, NORMAL_CLOSE); -} - -/**************************************************************************** - The guts of the unlink command, split out so it may be called by the NT SMB - code. -****************************************************************************/ - -NTSTATUS unlink_internals(connection_struct *conn, - struct smb_request *req, - uint32_t dirtype, - struct smb_filename *smb_fname, - bool has_wild) -{ - char *fname_dir = NULL; - char *fname_mask = NULL; - int count=0; - NTSTATUS status = NT_STATUS_OK; - struct smb_filename *smb_fname_dir = NULL; - TALLOC_CTX *ctx = talloc_tos(); - int ret; - - /* Split up the directory from the filename/mask. */ - status = split_fname_dir_mask(ctx, smb_fname->base_name, - &fname_dir, &fname_mask); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - - if (!VALID_STAT(smb_fname->st) && - mangle_is_mangled(fname_mask, conn->params)) { - char *new_mask = NULL; - mangle_lookup_name_from_8_3(ctx, fname_mask, - &new_mask, conn->params); - if (new_mask) { - TALLOC_FREE(fname_mask); - fname_mask = new_mask; - } - } - - if (!has_wild) { - - /* - * Only one file needs to be unlinked. Append the mask back - * onto the directory. - */ - TALLOC_FREE(smb_fname->base_name); - if (ISDOT(fname_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname->base_name = talloc_asprintf(smb_fname, - "%s", - fname_mask); - } else { - smb_fname->base_name = talloc_asprintf(smb_fname, - "%s/%s", - fname_dir, - fname_mask); - } - if (!smb_fname->base_name) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - if (dirtype == 0) { - dirtype = FILE_ATTRIBUTE_NORMAL; - } - - status = check_name(conn, smb_fname); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - status = do_unlink(conn, req, smb_fname, dirtype); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - count++; - } else { - struct smb_Dir *dir_hnd = NULL; - long offset = 0; - const char *dname = NULL; - char *talloced = NULL; - - if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) { - status = NT_STATUS_OBJECT_NAME_INVALID; - goto out; - } - if (dirtype == 0) { - dirtype = FILE_ATTRIBUTE_NORMAL; - } - - if (strequal(fname_mask,"????????.???")) { - TALLOC_FREE(fname_mask); - fname_mask = talloc_strdup(ctx, "*"); - if (!fname_mask) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - } - - smb_fname_dir = synthetic_smb_fname(talloc_tos(), - fname_dir, - NULL, - NULL, - smb_fname->twrp, - smb_fname->flags); - if (smb_fname_dir == NULL) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - - status = check_name(conn, smb_fname_dir); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - - dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask, - dirtype); - if (dir_hnd == NULL) { - status = map_nt_error_from_unix(errno); - goto out; - } - - /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then - the pattern matches against the long name, otherwise the short name - We don't implement this yet XXXX - */ - - status = NT_STATUS_NO_SUCH_FILE; - - while ((dname = ReadDirName(dir_hnd, &offset, - &smb_fname->st, &talloced))) { - TALLOC_CTX *frame = talloc_stackframe(); - char *p = NULL; - struct smb_filename *f = NULL; - - /* Quick check for "." and ".." */ - if (ISDOT(dname) || ISDOTDOT(dname)) { - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - continue; - } - - if (IS_VETO_PATH(conn, dname)) { - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - continue; - } - - if(!mask_match(dname, fname_mask, - conn->case_sensitive)) { - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - continue; - } - - if (ISDOT(fname_dir)) { - /* Ensure we use canonical names on open. */ - p = talloc_asprintf(smb_fname, "%s", dname); - } else { - p = talloc_asprintf(smb_fname, "%s/%s", - fname_dir, dname); - } - if (p == NULL) { - TALLOC_FREE(dir_hnd); - status = NT_STATUS_NO_MEMORY; - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - f = synthetic_smb_fname(frame, - p, - NULL, - &smb_fname->st, - smb_fname->twrp, - smb_fname->flags); - if (f == NULL) { - TALLOC_FREE(dir_hnd); - status = NT_STATUS_NO_MEMORY; - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - - ret = vfs_stat(conn, f); - if (ret != 0) { - status = map_nt_error_from_unix(errno); - TALLOC_FREE(dir_hnd); - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - - status = openat_pathref_fsp(conn->cwd_fsp, f); - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && - (f->flags & SMB_FILENAME_POSIX_PATH) && - S_ISLNK(f->st.st_ex_mode)) - { - status = NT_STATUS_OK; - } - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - - if (!is_visible_fsp(f->fsp)) { - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - continue; - } - - status = check_name(conn, f); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - - status = do_unlink(conn, req, f, dirtype); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - goto out; - } - - count++; - DBG_DEBUG("successful unlink [%s]\n", - smb_fname_str_dbg(f)); - - TALLOC_FREE(frame); - TALLOC_FREE(talloced); - } - TALLOC_FREE(dir_hnd); - } - - if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) { - status = map_nt_error_from_unix(errno); - } - - out: - TALLOC_FREE(smb_fname_dir); - TALLOC_FREE(fname_dir); - TALLOC_FREE(fname_mask); - return status; + return close_file_free(req, &fsp, NORMAL_CLOSE); } /**************************************************************************** @@ -3538,10 +3210,8 @@ void reply_unlink(struct smb_request *req) struct smb_filename *smb_fname = NULL; uint32_t dirtype; NTSTATUS status; - uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); + uint32_t ucf_flags = ucf_flags_from_smb_request(req); TALLOC_CTX *ctx = talloc_tos(); - bool has_wild = false; START_PROFILE(SMBunlink); @@ -3574,22 +3244,9 @@ void reply_unlink(struct smb_request *req) goto out; } - if (!req->posix_pathnames) { - char *lcomp = get_original_lcomp(ctx, - conn, - name, - ucf_flags); - if (lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - has_wild = ms_has_wild(lcomp); - TALLOC_FREE(lcomp); - } - DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname))); - status = unlink_internals(conn, req, dirtype, smb_fname, has_wild); + status = unlink_internals(conn, req, dirtype, smb_fname); if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->xconn, req->mid)) { /* We have re-scheduled this call. */ @@ -3823,8 +3480,10 @@ static void send_file_readbraw(connection_struct *conn, * reply_readbraw has already checked the length. */ - if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) && - lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { + if ( !req_is_in_chain(req) && + (nread > 0) && + !fsp_is_alternate_stream(fsp) && + lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { ssize_t sendfile_read = -1; char header[4]; DATA_BLOB header_blob; @@ -4035,9 +3694,13 @@ void reply_readbraw(struct smb_request *req) /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)maxcount, + READ_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_readbraw_error(xconn); @@ -4132,6 +3795,7 @@ void reply_lockread(struct smb_request *req) .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = WRITE_LOCK, + .lock_flav = WINDOWS_LOCK, .count = SVAL(req->vwv+1, 0), .offset = IVAL_TO_SMB_OFF_T(req->vwv+2, 0), }; @@ -4143,7 +3807,6 @@ void reply_lockread(struct smb_request *req) fsp, 0, false, /* large_offset */ - WINDOWS_LOCK, 1, lck); if (subreq == NULL) { @@ -4302,9 +3965,13 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n", data = smb_buf(req->outbuf) + 3; - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)numtoread, + READ_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -4379,9 +4046,13 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, int saved_errno = 0; NTSTATUS status; - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)smb_maxcnt, + READ_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -4396,7 +4067,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, if (!req_is_in_chain(req) && !req->encrypted && - (fsp->base_fsp == NULL) && + !fsp_is_alternate_stream(fsp) && lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) { uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */]; DATA_BLOB header; @@ -4619,7 +4290,7 @@ static size_t calc_max_read_pdu(const struct smb_request *req) return 0x1FFFF; } - if (!lp_unix_extensions()) { + if (!lp_smb1_unix_extensions()) { return 0x1FFFF; } @@ -4902,9 +4573,13 @@ void reply_writebraw(struct smb_request *req) } if (!fsp->print_file) { - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)tcount, + WRITE_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -5117,9 +4792,13 @@ void reply_writeunlock(struct smb_request *req) } if (!fsp->print_file && numtowrite > 0) { - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)numtowrite, + WRITE_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -5161,10 +4840,11 @@ void reply_writeunlock(struct smb_request *req) .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = UNLOCK_LOCK, + .lock_flav = WINDOWS_LOCK, .offset = startpos, .count = numtowrite, }; - status = smbd_do_unlocking(req, fsp, 1, &l, WINDOWS_LOCK); + status = smbd_do_unlocking(req, fsp, 1, &l); if (NT_STATUS_V(status)) { reply_nterror(req, status); goto out; @@ -5247,9 +4927,13 @@ void reply_write(struct smb_request *req) } if (!fsp->print_file) { - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)numtowrite, + WRITE_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -5380,7 +5064,7 @@ bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn, DEBUG(10,("is_valid_writeX_buffer: printing tid\n")); return false; } - if (fsp->base_fsp != NULL) { + if (fsp_is_alternate_stream(fsp)) { DEBUG(10,("is_valid_writeX_buffer: stream fsp\n")); return false; } @@ -5543,9 +5227,13 @@ void reply_write_and_X(struct smb_request *req) /* NT_STATUS_RETRY - fall through to sync write. */ } - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)numtowrite, + WRITE_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -5970,7 +5658,7 @@ static void reply_exit_done(struct tevent_req *req) smb_request_done(smb1req); END_PROFILE(SMBexit); } - close_file(NULL, fsp, SHUTDOWN_CLOSE); + close_file_free(NULL, &fsp, SHUTDOWN_CLOSE); } reply_outbuf(smb1req, 0, 0); @@ -6046,12 +5734,12 @@ void reply_close(struct smb_request *smb1req) } /* - * close_file() returns the unix errno if an error was detected on + * close_file_free() returns the unix errno if an error was detected on * close - normally this is due to a disk full error. If not then it * was probably an I/O error. */ - status = close_file(smb1req, fsp, NORMAL_CLOSE); + status = close_file_free(smb1req, &fsp, NORMAL_CLOSE); done: if (!NT_STATUS_IS_OK(status)) { reply_nterror(smb1req, status); @@ -6177,7 +5865,7 @@ static void reply_close_done(struct tevent_req *req) return; } - status = close_file(smb1req, state->fsp, NORMAL_CLOSE); + status = close_file_free(smb1req, &state->fsp, NORMAL_CLOSE); if (NT_STATUS_IS_OK(status)) { reply_outbuf(smb1req, 0, 0); } else { @@ -6245,9 +5933,13 @@ void reply_writeclose(struct smb_request *req) } if (fsp->print_file == NULL) { - init_strict_lock_struct(fsp, (uint64_t)req->smbpid, - (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK, - &lock); + init_strict_lock_struct(fsp, + (uint64_t)req->smbpid, + (uint64_t)startpos, + (uint64_t)numtowrite, + WRITE_LOCK, + lp_posix_cifsu_locktype(fsp), + &lock); if (!SMB_VFS_STRICT_LOCK_CHECK(conn, fsp, &lock)) { reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT); @@ -6272,8 +5964,7 @@ void reply_writeclose(struct smb_request *req) if (numtowrite) { DEBUG(3,("reply_writeclose: zero length write doesn't close " "file %s\n", fsp_str_dbg(fsp))); - close_status = close_file(req, fsp, NORMAL_CLOSE); - fsp = NULL; + close_status = close_file_free(req, &fsp, NORMAL_CLOSE); } if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) { @@ -6338,6 +6029,7 @@ void reply_lock(struct smb_request *req) .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = WRITE_LOCK, + .lock_flav = WINDOWS_LOCK, .count = IVAL(req->vwv+1, 0), .offset = IVAL(req->vwv+3, 0), }; @@ -6355,7 +6047,6 @@ void reply_lock(struct smb_request *req) fsp, 0, false, /* large_offset */ - WINDOWS_LOCK, 1, lck); if (subreq == NULL) { @@ -6430,11 +6121,12 @@ void reply_unlock(struct smb_request *req) .req_guid = smbd_request_guid(req, 0), .smblctx = req->smbpid, .brltype = UNLOCK_LOCK, + .lock_flav = WINDOWS_LOCK, .offset = IVAL(req->vwv+3, 0), .count = IVAL(req->vwv+1, 0), }; - status = smbd_do_unlocking(req, fsp, 1, &lck, WINDOWS_LOCK); + status = smbd_do_unlocking(req, fsp, 1, &lck); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -6820,7 +6512,7 @@ void reply_printclose(struct smb_request *req) DEBUG(3,("printclose fd=%d %s\n", fsp_get_io_fd(fsp), fsp_fnum_dbg(fsp))); - status = close_file(req, fsp, NORMAL_CLOSE); + status = close_file_free(req, &fsp, NORMAL_CLOSE); if(!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -7223,7 +6915,7 @@ void reply_rmdir(struct smb_request *req) status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY); if (!NT_STATUS_IS_OK(status)) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, status); goto out; } @@ -7231,12 +6923,12 @@ void reply_rmdir(struct smb_request *req) if (!set_delete_on_close(fsp, true, conn->session_info->security_token, conn->session_info->unix_token)) { - close_file(req, fsp, ERROR_CLOSE); + close_file_free(req, &fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_ACCESS_DENIED); goto out; } - status = close_file(req, fsp, NORMAL_CLOSE); + status = close_file_free(req, &fsp, NORMAL_CLOSE); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); } else { @@ -7250,133 +6942,6 @@ void reply_rmdir(struct smb_request *req) return; } -/******************************************************************* - Resolve wildcards in a filename rename. -********************************************************************/ - -static bool resolve_wildcards(TALLOC_CTX *ctx, - const char *name1, - const char *name2, - char **pp_newname) -{ - char *name2_copy = NULL; - char *root1 = NULL; - char *root2 = NULL; - char *ext1 = NULL; - char *ext2 = NULL; - char *p,*p2, *pname1, *pname2; - - name2_copy = talloc_strdup(ctx, name2); - if (!name2_copy) { - return False; - } - - pname1 = strrchr_m(name1,'/'); - pname2 = strrchr_m(name2_copy,'/'); - - if (!pname1 || !pname2) { - return False; - } - - /* Truncate the copy of name2 at the last '/' */ - *pname2 = '\0'; - - /* Now go past the '/' */ - pname1++; - pname2++; - - root1 = talloc_strdup(ctx, pname1); - root2 = talloc_strdup(ctx, pname2); - - if (!root1 || !root2) { - return False; - } - - p = strrchr_m(root1,'.'); - if (p) { - *p = 0; - ext1 = talloc_strdup(ctx, p+1); - } else { - ext1 = talloc_strdup(ctx, ""); - } - p = strrchr_m(root2,'.'); - if (p) { - *p = 0; - ext2 = talloc_strdup(ctx, p+1); - } else { - ext2 = talloc_strdup(ctx, ""); - } - - if (!ext1 || !ext2) { - return False; - } - - p = root1; - p2 = root2; - while (*p2) { - if (*p2 == '?') { - /* Hmmm. Should this be mb-aware ? */ - *p2 = *p; - p2++; - } else if (*p2 == '*') { - *p2 = '\0'; - root2 = talloc_asprintf(ctx, "%s%s", - root2, - p); - if (!root2) { - return False; - } - break; - } else { - p2++; - } - if (*p) { - p++; - } - } - - p = ext1; - p2 = ext2; - while (*p2) { - if (*p2 == '?') { - /* Hmmm. Should this be mb-aware ? */ - *p2 = *p; - p2++; - } else if (*p2 == '*') { - *p2 = '\0'; - ext2 = talloc_asprintf(ctx, "%s%s", - ext2, - p); - if (!ext2) { - return False; - } - break; - } else { - p2++; - } - if (*p) { - p++; - } - } - - if (*ext2) { - *pp_newname = talloc_asprintf(ctx, "%s/%s.%s", - name2_copy, - root2, - ext2); - } else { - *pp_newname = talloc_asprintf(ctx, "%s/%s", - name2_copy, - root2); - } - - if (!*pp_newname) { - return False; - } - - return True; -} - /**************************************************************************** Ensure open files have their names updated. Updated to notify other smbd's asynchronously. @@ -7537,7 +7102,7 @@ static NTSTATUS parent_dirname_compatible_open(connection_struct *conn, return status; } - ret = SMB_VFS_LSTAT(conn, smb_fname_parent); + ret = vfs_stat(conn, smb_fname_parent); if (ret == -1) { return map_nt_error_from_unix(errno); } @@ -7579,11 +7144,10 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, uint32_t access_mask = SEC_DIR_ADD_FILE; bool dst_exists, old_is_stream, new_is_stream; int ret; - - status = check_name(conn, smb_fname_dst_in); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + bool case_sensitive = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ? + true : conn->case_sensitive; + bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ? + true : conn->case_preserve; status = parent_dirname_compatible_open(conn, smb_fname_dst_in); if (!NT_STATUS_IS_OK(status)) { @@ -7609,7 +7173,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, * the rename (user is trying to change the case of the * filename). */ - if (!conn->case_sensitive && conn->case_preserve && + if (!case_sensitive && case_preserve && strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) && strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) { char *fname_dst_parent = NULL; @@ -7737,7 +7301,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, goto out; } - dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0; + dst_exists = vfs_stat(conn, smb_fname_dst) == 0; if(!replace_if_exists && dst_exists) { DEBUG(3, ("rename_internals_fsp: dest exists doing rename " @@ -8012,170 +7576,72 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, connection_struct *conn, struct smb_request *req, struct smb_filename *smb_fname_src, - const char *src_original_lcomp, struct smb_filename *smb_fname_dst, const char *dst_original_lcomp, uint32_t attrs, bool replace_if_exists, uint32_t access_mask) { - char *fname_src_dir = NULL; - struct smb_filename *smb_fname_src_dir = NULL; - char *fname_src_mask = NULL; - int count=0; NTSTATUS status = NT_STATUS_OK; - struct smb_Dir *dir_hnd = NULL; - const char *dname = NULL; - char *talloced = NULL; - long offset = 0; int create_options = 0; struct smb2_create_blobs *posx = NULL; int rc; - bool src_has_wild = false; - bool dest_has_wild = false; + struct files_struct *fsp = NULL; + bool posix_pathname = (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH); + bool case_sensitive = posix_pathname ? true : conn->case_sensitive; + bool case_preserve = posix_pathname ? true : conn->case_preserve; + bool short_case_preserve = posix_pathname ? true : + conn->short_case_preserve; - /* - * Split the old name into directory and last component - * strings. Note that unix_convert may have stripped off a - * leading ./ from both name and newname if the rename is - * at the root of the share. We need to make sure either both - * name and newname contain a / character or neither of them do - * as this is checked in resolve_wildcards(). - */ + if (posix_pathname) { + status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777); + if (!NT_STATUS_IS_OK(status)) { + DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n", + nt_errstr(status)); + goto out; + } + } - /* Split up the directory from the filename/mask. */ - status = split_fname_dir_mask(ctx, smb_fname_src->base_name, - &fname_src_dir, &fname_src_mask); - if (!NT_STATUS_IS_OK(status)) { - status = NT_STATUS_NO_MEMORY; + DBG_NOTICE("case_sensitive = %d, " + "case_preserve = %d, short case preserve = %d, " + "directory = %s, newname = %s, " + "last_component_dest = %s\n", + case_sensitive, case_preserve, + short_case_preserve, + smb_fname_str_dbg(smb_fname_src), + smb_fname_str_dbg(smb_fname_dst), + dst_original_lcomp); + + ZERO_STRUCT(smb_fname_src->st); + + rc = vfs_stat(conn, smb_fname_src); + if (rc == -1) { + status = map_nt_error_from_unix_common(errno); goto out; } - if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) { - /* - * Check the wildcard mask *before* - * unmangling. As mangling is done - * for names that can't be returned - * to Windows the unmangled name may - * contain Windows wildcard characters. - */ - if (src_original_lcomp != NULL) { - src_has_wild = ms_has_wild(src_original_lcomp); - } - dest_has_wild = ms_has_wild(dst_original_lcomp); - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - - if (!VALID_STAT(smb_fname_src->st) && - mangle_is_mangled(fname_src_mask, conn->params)) { - char *new_mask = NULL; - mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask, - conn->params); - if (new_mask) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = new_mask; - } - } - - if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) { - status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777); - if (!NT_STATUS_IS_OK(status)) { - DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n", - nt_errstr(status)); + status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src); + if (!NT_STATUS_IS_OK(status)) { + if (!NT_STATUS_EQUAL(status, + NT_STATUS_OBJECT_NAME_NOT_FOUND)) { goto out; } - } - - if (!src_has_wild) { - files_struct *fsp; - /* - * Only one file needs to be renamed. Append the mask back - * onto the directory. + * Possible symlink src. */ - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s", - fname_src_mask); - } else { - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s/%s", - fname_src_dir, - fname_src_mask); - } - if (!smb_fname_src->base_name) { - status = NT_STATUS_NO_MEMORY; + if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) { goto out; } - - DEBUG(3, ("rename_internals: case_sensitive = %d, " - "case_preserve = %d, short case preserve = %d, " - "directory = %s, newname = %s, " - "last_component_dest = %s\n", - conn->case_sensitive, conn->case_preserve, - conn->short_case_preserve, - smb_fname_str_dbg(smb_fname_src), - smb_fname_str_dbg(smb_fname_dst), - dst_original_lcomp)); - - /* The dest name still may have wildcards. */ - if (dest_has_wild) { - char *fname_dst_mod = NULL; - if (!resolve_wildcards(smb_fname_dst, - smb_fname_src->base_name, - smb_fname_dst->base_name, - &fname_dst_mod)) { - DEBUG(6, ("rename_internals: resolve_wildcards " - "%s %s failed\n", - smb_fname_src->base_name, - smb_fname_dst->base_name)); - status = NT_STATUS_NO_MEMORY; - goto out; - } - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = fname_dst_mod; - } - - ZERO_STRUCT(smb_fname_src->st); - - rc = vfs_stat(conn, smb_fname_src); - if (rc == -1) { - status = map_nt_error_from_unix_common(errno); + if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) { goto out; } + } - status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - if (!NT_STATUS_EQUAL(status, - NT_STATUS_OBJECT_NAME_NOT_FOUND)) { - goto out; - } - /* - * Possible symlink src. - */ - if (!(smb_fname_src->flags & SMB_FILENAME_POSIX_PATH)) { - goto out; - } - if (!S_ISLNK(smb_fname_src->st.st_ex_mode)) { - goto out; - } - } - - if (S_ISDIR(smb_fname_src->st.st_ex_mode)) { - create_options |= FILE_DIRECTORY_FILE; - } + if (S_ISDIR(smb_fname_src->st.st_ex_mode)) { + create_options |= FILE_DIRECTORY_FILE; + } - status = SMB_VFS_CREATE_FILE( + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ smb_fname_src, /* fname */ @@ -8196,223 +7662,28 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, posx, /* in_context_blobs */ NULL); /* out_context_blobs */ - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("Could not open rename source %s: %s\n", - smb_fname_str_dbg(smb_fname_src), - nt_errstr(status))); - goto out; - } - - status = rename_internals_fsp(conn, - fsp, - smb_fname_dst, - dst_original_lcomp, - attrs, - replace_if_exists); - - close_file(req, fsp, NORMAL_CLOSE); - - DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n", - nt_errstr(status), smb_fname_str_dbg(smb_fname_src), - smb_fname_str_dbg(smb_fname_dst))); - - goto out; - } - - /* - * Wildcards - process each file that matches. - */ - if (strequal(fname_src_mask, "????????.???")) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = talloc_strdup(ctx, "*"); - if (!fname_src_mask) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - } - - smb_fname_src_dir = synthetic_smb_fname(talloc_tos(), - fname_src_dir, - NULL, - NULL, - smb_fname_src->twrp, - smb_fname_src->flags); - if (smb_fname_src_dir == NULL) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - - status = check_name(conn, smb_fname_src_dir); if (!NT_STATUS_IS_OK(status)) { + DBG_NOTICE("Could not open rename source %s: %s\n", + smb_fname_str_dbg(smb_fname_src), + nt_errstr(status)); goto out; } - dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask, - attrs); - if (dir_hnd == NULL) { - status = map_nt_error_from_unix(errno); - goto out; - } - - status = NT_STATUS_NO_SUCH_FILE; - /* - * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - * - gentest fix. JRA - */ - - while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st, - &talloced))) { - files_struct *fsp = NULL; - char *destname = NULL; - bool sysdir_entry = False; - - /* Quick check for "." and ".." */ - if (ISDOT(dname) || ISDOTDOT(dname)) { - if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - sysdir_entry = True; - } else { - TALLOC_FREE(talloced); - continue; - } - } - - if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) { - TALLOC_FREE(talloced); - continue; - } - - if (sysdir_entry) { - status = NT_STATUS_OBJECT_NAME_INVALID; - break; - } - - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s", - dname); - } else { - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s/%s", - fname_src_dir, - dname); - } - if (!smb_fname_src->base_name) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - - if (!resolve_wildcards(ctx, smb_fname_src->base_name, - smb_fname_dst->base_name, - &destname)) { - DEBUG(6, ("resolve_wildcards %s %s failed\n", - smb_fname_src->base_name, destname)); - TALLOC_FREE(talloced); - continue; - } - if (!destname) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = destname; - - ZERO_STRUCT(smb_fname_src->st); - vfs_stat(conn, smb_fname_src); - - status = openat_pathref_fsp(conn->cwd_fsp, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - DBG_INFO("openat_pathref_fsp [%s] failed: %s\n", - smb_fname_str_dbg(smb_fname_src), - nt_errstr(status)); - break; - } - - if (!is_visible_fsp(smb_fname_src->fsp)) { - TALLOC_FREE(talloced); - continue; - } - - create_options = 0; - - if (S_ISDIR(smb_fname_src->st.st_ex_mode)) { - create_options |= FILE_DIRECTORY_FILE; - } - - status = SMB_VFS_CREATE_FILE( - conn, /* conn */ - req, /* req */ - smb_fname_src, /* fname */ - access_mask, /* access_mask */ - (FILE_SHARE_READ | /* share_access */ - FILE_SHARE_WRITE), - FILE_OPEN, /* create_disposition*/ - create_options, /* create_options */ - 0, /* file_attributes */ - 0, /* oplock_request */ - NULL, /* lease */ - 0, /* allocation_size */ - 0, /* private_flags */ - NULL, /* sd */ - NULL, /* ea_list */ - &fsp, /* result */ - NULL, /* pinfo */ - posx, /* in_context_blobs */ - NULL); /* out_context_blobs */ - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE " - "returned %s rename %s -> %s\n", - nt_errstr(status), - smb_fname_str_dbg(smb_fname_src), - smb_fname_str_dbg(smb_fname_dst))); - break; - } - - dst_original_lcomp = talloc_strdup(smb_fname_dst, dname); - if (dst_original_lcomp == NULL) { - status = NT_STATUS_NO_MEMORY; - goto out; - } - - status = rename_internals_fsp(conn, + status = rename_internals_fsp(conn, fsp, smb_fname_dst, dst_original_lcomp, attrs, replace_if_exists); - close_file(req, fsp, NORMAL_CLOSE); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("rename_internals_fsp returned %s for " - "rename %s -> %s\n", nt_errstr(status), - smb_fname_str_dbg(smb_fname_src), - smb_fname_str_dbg(smb_fname_dst))); - break; - } + close_file_free(req, &fsp, NORMAL_CLOSE); - count++; - - DEBUG(3,("rename_internals: doing rename on %s -> " - "%s\n", smb_fname_str_dbg(smb_fname_src), - smb_fname_str_dbg(smb_fname_src))); - TALLOC_FREE(talloced); - } - TALLOC_FREE(dir_hnd); - - if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) { - status = map_nt_error_from_unix(errno); - } + DBG_NOTICE("Error %s rename %s -> %s\n", + nt_errstr(status), smb_fname_str_dbg(smb_fname_src), + smb_fname_str_dbg(smb_fname_dst)); out: TALLOC_FREE(posx); - TALLOC_FREE(talloced); - TALLOC_FREE(smb_fname_src_dir); - TALLOC_FREE(fname_src_dir); - TALLOC_FREE(fname_src_mask); return status; } @@ -8430,13 +7701,10 @@ void reply_mv(struct smb_request *req) NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); struct smb_filename *smb_fname_src = NULL; - const char *src_original_lcomp = NULL; struct smb_filename *smb_fname_dst = NULL; const char *dst_original_lcomp = NULL; - uint32_t src_ucf_flags = ucf_flags_from_smb_request(req) | - (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0); - uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req) | - (!req->posix_pathnames ? UCF_ALWAYS_ALLOW_WCARD_LCOMP : 0); + uint32_t src_ucf_flags = ucf_flags_from_smb_request(req); + uint32_t dst_ucf_flags = ucf_flags_from_smb_request(req); bool stream_rename = false; START_PROFILE(SMBmv); @@ -8492,16 +7760,6 @@ void reply_mv(struct smb_request *req) goto out; } - /* Get the last component of the source for rename_internals(). */ - src_original_lcomp = get_original_lcomp(ctx, - conn, - name, - dst_ucf_flags); - if (src_original_lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - status = filename_convert(ctx, conn, newname, @@ -8548,7 +7806,6 @@ void reply_mv(struct smb_request *req) conn, req, smb_fname_src, - src_original_lcomp, smb_fname_dst, dst_original_lcomp, attrs, @@ -8713,7 +7970,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, NULL, NULL); /* create context */ if (!NT_STATUS_IS_OK(status)) { - close_file(NULL, fsp1, ERROR_CLOSE); + close_file_free(NULL, &fsp1, ERROR_CLOSE); goto out; } @@ -8723,8 +7980,8 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, DEBUG(0, ("error - vfs lseek returned error %s\n", strerror(errno))); status = map_nt_error_from_unix(errno); - close_file(NULL, fsp1, ERROR_CLOSE); - close_file(NULL, fsp2, ERROR_CLOSE); + close_file_free(NULL, &fsp1, ERROR_CLOSE); + close_file_free(NULL, &fsp2, ERROR_CLOSE); goto out; } } @@ -8736,7 +7993,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, ret = 0; } - close_file(NULL, fsp1, NORMAL_CLOSE); + close_file_free(NULL, &fsp1, NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime); @@ -8747,7 +8004,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, * Thus we don't look at the error return from the * close of fsp1. */ - status = close_file(NULL, fsp2, NORMAL_CLOSE); + status = close_file_free(NULL, &fsp2, NORMAL_CLOSE); if (!NT_STATUS_IS_OK(status)) { goto out; @@ -8767,416 +8024,22 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, /**************************************************************************** Reply to a file copy. + + From MS-CIFS. + + This command was introduced in the LAN Manager 1.0 dialect + It was rendered obsolete in the NT LAN Manager dialect. + This command was used to perform server-side file copies, but + is no longer used. Clients SHOULD + NOT send requests using this command code. + Servers receiving requests with this command code + SHOULD return STATUS_NOT_IMPLEMENTED (ERRDOS/ERRbadfunc). ****************************************************************************/ void reply_copy(struct smb_request *req) { - connection_struct *conn = req->conn; - struct smb_filename *smb_fname_src = NULL; - struct smb_filename *smb_fname_src_dir = NULL; - struct smb_filename *smb_fname_dst = NULL; - char *fname_src = NULL; - char *fname_dst = NULL; - char *fname_src_mask = NULL; - char *fname_src_dir = NULL; - const char *p; - int count=0; - int error = ERRnoaccess; - int tid2; - int ofun; - int flags; - bool target_is_directory=False; - bool source_has_wild = False; - bool dest_has_wild = False; - NTSTATUS status; - uint32_t ucf_flags_src = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); - uint32_t ucf_flags_dst = UCF_ALWAYS_ALLOW_WCARD_LCOMP | - ucf_flags_from_smb_request(req); - TALLOC_CTX *ctx = talloc_tos(); - START_PROFILE(SMBcopy); - - if (req->wct < 3) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto out; - } - - tid2 = SVAL(req->vwv+0, 0); - ofun = SVAL(req->vwv+1, 0); - flags = SVAL(req->vwv+2, 0); - - p = (const char *)req->buf; - p += srvstr_get_path_req(ctx, req, &fname_src, p, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - p += srvstr_get_path_req(ctx, req, &fname_dst, p, STR_TERMINATE, - &status); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst)); - - if (tid2 != conn->cnum) { - /* can't currently handle inter share copies XXXX */ - DEBUG(3,("Rejecting inter-share copy\n")); - reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE); - goto out; - } - - status = filename_convert(ctx, conn, - fname_src, - ucf_flags_src, - 0, - &smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - goto out; - } - reply_nterror(req, status); - goto out; - } - - status = filename_convert(ctx, conn, - fname_dst, - ucf_flags_dst, - 0, - &smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - goto out; - } - reply_nterror(req, status); - goto out; - } - - target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st); - - if ((flags&1) && target_is_directory) { - reply_nterror(req, NT_STATUS_NO_SUCH_FILE); - goto out; - } - - if ((flags&2) && !target_is_directory) { - reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND); - goto out; - } - - if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) { - /* wants a tree copy! XXXX */ - DEBUG(3,("Rejecting tree copy\n")); - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - goto out; - } - - /* Split up the directory from the filename/mask. */ - status = split_fname_dir_mask(ctx, smb_fname_src->base_name, - &fname_src_dir, &fname_src_mask); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (!req->posix_pathnames) { - char *orig_src_lcomp = NULL; - char *orig_dst_lcomp = NULL; - /* - * Check the wildcard mask *before* - * unmangling. As mangling is done - * for names that can't be returned - * to Windows the unmangled name may - * contain Windows wildcard characters. - */ - orig_src_lcomp = get_original_lcomp(ctx, - conn, - fname_src, - ucf_flags_src); - if (orig_src_lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - orig_dst_lcomp = get_original_lcomp(ctx, - conn, - fname_dst, - ucf_flags_dst); - if (orig_dst_lcomp == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - source_has_wild = ms_has_wild(orig_src_lcomp); - dest_has_wild = ms_has_wild(orig_dst_lcomp); - TALLOC_FREE(orig_src_lcomp); - TALLOC_FREE(orig_dst_lcomp); - } - - /* - * We should only check the mangled cache - * here if unix_convert failed. This means - * that the path in 'mask' doesn't exist - * on the file system and so we need to look - * for a possible mangle. This patch from - * Tine Smukavec . - */ - if (!VALID_STAT(smb_fname_src->st) && - mangle_is_mangled(fname_src_mask, conn->params)) { - char *new_mask = NULL; - mangle_lookup_name_from_8_3(ctx, fname_src_mask, - &new_mask, conn->params); - - /* Use demangled name if one was successfully found. */ - if (new_mask) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = new_mask; - } - } - - if (!source_has_wild) { - - /* - * Only one file needs to be copied. Append the mask back onto - * the directory. - */ - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s", - fname_src_mask); - } else { - smb_fname_src->base_name = talloc_asprintf(smb_fname_src, - "%s/%s", - fname_src_dir, - fname_src_mask); - } - if (!smb_fname_src->base_name) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (dest_has_wild) { - char *fname_dst_mod = NULL; - if (!resolve_wildcards(smb_fname_dst, - smb_fname_src->base_name, - smb_fname_dst->base_name, - &fname_dst_mod)) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = fname_dst_mod; - } - - status = check_name(conn, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - status = check_name(conn, smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst, - ofun, count, target_is_directory); - - if(!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } else { - count++; - } - } else { - struct smb_Dir *dir_hnd = NULL; - const char *dname = NULL; - char *talloced = NULL; - long offset = 0; - - /* - * There is a wildcard that requires us to actually read the - * src dir and copy each file matching the mask to the dst. - * Right now streams won't be copied, but this could - * presumably be added with a nested loop for reach dir entry. - */ - SMB_ASSERT(!smb_fname_src->stream_name); - SMB_ASSERT(!smb_fname_dst->stream_name); - - smb_fname_src->stream_name = NULL; - smb_fname_dst->stream_name = NULL; - - if (strequal(fname_src_mask,"????????.???")) { - TALLOC_FREE(fname_src_mask); - fname_src_mask = talloc_strdup(ctx, "*"); - if (!fname_src_mask) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - } - - smb_fname_src_dir = synthetic_smb_fname(talloc_tos(), - fname_src_dir, - NULL, - NULL, - smb_fname_src->twrp, - smb_fname_src->flags); - if (smb_fname_src_dir == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - status = check_name(conn, smb_fname_src_dir); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - goto out; - } - - dir_hnd = OpenDir(ctx, - conn, - smb_fname_src_dir, - fname_src_mask, - 0); - if (dir_hnd == NULL) { - status = map_nt_error_from_unix(errno); - reply_nterror(req, status); - goto out; - } - - error = ERRbadfile; - - /* Iterate over the src dir copying each entry to the dst. */ - while ((dname = ReadDirName(dir_hnd, &offset, - &smb_fname_src->st, &talloced))) { - char *destname = NULL; - - if (ISDOT(dname) || ISDOTDOT(dname)) { - TALLOC_FREE(talloced); - continue; - } - - if (IS_VETO_PATH(conn, dname)) { - TALLOC_FREE(talloced); - continue; - } - - if(!mask_match(dname, fname_src_mask, - conn->case_sensitive)) { - TALLOC_FREE(talloced); - continue; - } - - error = ERRnoaccess; - - /* Get the src smb_fname struct setup. */ - TALLOC_FREE(smb_fname_src->base_name); - if (ISDOT(fname_src_dir)) { - /* Ensure we use canonical names on open. */ - smb_fname_src->base_name = - talloc_asprintf(smb_fname_src, "%s", - dname); - } else { - smb_fname_src->base_name = - talloc_asprintf(smb_fname_src, "%s/%s", - fname_src_dir, dname); - } - - if (!smb_fname_src->base_name) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - if (!resolve_wildcards(ctx, smb_fname_src->base_name, - smb_fname_dst->base_name, - &destname)) { - TALLOC_FREE(talloced); - continue; - } - if (!destname) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, NT_STATUS_NO_MEMORY); - goto out; - } - - TALLOC_FREE(smb_fname_dst->base_name); - smb_fname_dst->base_name = destname; - - ZERO_STRUCT(smb_fname_src->st); - vfs_stat(conn, smb_fname_src); - - status = openat_pathref_fsp(conn->cwd_fsp, - smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - DBG_INFO("openat_pathref_fsp [%s] failed: %s\n", - smb_fname_str_dbg(smb_fname_src), - nt_errstr(status)); - break; - } - - if (!is_visible_fsp(smb_fname_src->fsp)) { - TALLOC_FREE(talloced); - continue; - } - - status = check_name(conn, smb_fname_src); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, status); - goto out; - } - - status = check_name(conn, smb_fname_dst); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(dir_hnd); - TALLOC_FREE(talloced); - reply_nterror(req, status); - goto out; - } - - DEBUG(3,("reply_copy : doing copy on %s -> %s\n", - smb_fname_src->base_name, - smb_fname_dst->base_name)); - - status = copy_file(ctx, conn, smb_fname_src, - smb_fname_dst, ofun, count, - target_is_directory); - if (NT_STATUS_IS_OK(status)) { - count++; - } - - TALLOC_FREE(talloced); - } - TALLOC_FREE(dir_hnd); - } - - if (count == 0) { - reply_nterror(req, dos_to_ntstatus(ERRDOS, error)); - goto out; - } - - reply_outbuf(req, 1, 0); - SSVAL(req->outbuf,smb_vwv0,count); - out: - TALLOC_FREE(smb_fname_src); - TALLOC_FREE(smb_fname_src_dir); - TALLOC_FREE(smb_fname_dst); - TALLOC_FREE(fname_src); - TALLOC_FREE(fname_dst); - TALLOC_FREE(fname_src_mask); - TALLOC_FREE(fname_src_dir); - + reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED); END_PROFILE(SMBcopy); return; } @@ -9245,7 +8108,6 @@ struct smbd_do_unlocking_state { struct files_struct *fsp; uint16_t num_ulocks; struct smbd_lock_element *ulocks; - enum brl_flavour lock_flav; NTSTATUS status; }; @@ -9257,7 +8119,6 @@ static void smbd_do_unlocking_fn( { struct smbd_do_unlocking_state *state = private_data; struct files_struct *fsp = state->fsp; - enum brl_flavour lock_flav = state->lock_flav; uint16_t i; for (i = 0; i < state->num_ulocks; i++) { @@ -9277,7 +8138,7 @@ static void smbd_do_unlocking_fn( } state->status = do_unlock( - fsp, e->smblctx, e->count, e->offset, lock_flav); + fsp, e->smblctx, e->count, e->offset, e->lock_flav); DBG_DEBUG("do_unlock returned %s\n", nt_errstr(state->status)); @@ -9293,14 +8154,12 @@ static void smbd_do_unlocking_fn( NTSTATUS smbd_do_unlocking(struct smb_request *req, files_struct *fsp, uint16_t num_ulocks, - struct smbd_lock_element *ulocks, - enum brl_flavour lock_flav) + struct smbd_lock_element *ulocks) { struct smbd_do_unlocking_state state = { .fsp = fsp, .num_ulocks = num_ulocks, .ulocks = ulocks, - .lock_flav = lock_flav, }; NTSTATUS status; @@ -9483,6 +8342,7 @@ void reply_lockingX(struct smb_request *req) ulocks[i].offset = get_lock_offset( data, i, large_file_format); ulocks[i].brltype = UNLOCK_LOCK; + ulocks[i].lock_flav = WINDOWS_LOCK; } /* @@ -9492,7 +8352,6 @@ void reply_lockingX(struct smb_request *req) ok = smbd_smb1_brl_finish_by_lock( fsp, large_file_format, - WINDOWS_LOCK, ulocks[0], NT_STATUS_OK); if (ok) { @@ -9504,7 +8363,7 @@ void reply_lockingX(struct smb_request *req) } status = smbd_do_unlocking( - req, fsp, num_ulocks, ulocks, WINDOWS_LOCK); + req, fsp, num_ulocks, ulocks); TALLOC_FREE(ulocks); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBlockingX); @@ -9538,6 +8397,7 @@ void reply_lockingX(struct smb_request *req) locks[i].count = get_lock_count(data, i, large_file_format); locks[i].offset = get_lock_offset(data, i, large_file_format); locks[i].brltype = brltype; + locks[i].lock_flav = WINDOWS_LOCK; } if (locktype & LOCKING_ANDX_CANCEL_LOCK) { @@ -9557,7 +8417,6 @@ void reply_lockingX(struct smb_request *req) ok = smbd_smb1_brl_finish_by_lock( fsp, large_file_format, - WINDOWS_LOCK, locks[0], /* Windows only cancels the first lock */ NT_STATUS_FILE_LOCK_CONFLICT); @@ -9581,7 +8440,6 @@ void reply_lockingX(struct smb_request *req) fsp, lock_timeout, large_file_format, - WINDOWS_LOCK, num_locks, locks); if (subreq == NULL) {