}
}
- if (!posix_path && !stream_started && *s == ':') {
+ if ((*s == ':') && !posix_path && !stream_started) {
if (*p_last_component_contains_wcard) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
********************************************************************/
static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
- uint16 dirtype, SMB_STRUCT_STAT *pst)
+ uint16 dirtype)
{
uint32 fmode;
return NT_STATUS_NO_SUCH_FILE;
}
- if (S_ISDIR(pst->st_ex_mode)) {
+ if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
if (fsp->posix_open) {
return NT_STATUS_OK;
}
return NT_STATUS_OBJECT_NAME_INVALID;
#endif /* JRATEST */
- /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
-
- On a Windows share, a file with read-only dosmode can be opened with
- DELETE_ACCESS. But on a Samba share (delete readonly = no), it
- fails with NT_STATUS_CANNOT_DELETE error.
-
- This semantic causes a problem that a user can not
- rename a file with read-only dosmode on a Samba share
- from a Windows command prompt (i.e. cmd.exe, but can rename
- from Windows Explorer).
- */
-
- if (!lp_delete_readonly(SNUM(conn))) {
- if (fattr & aRONLY) {
- return NT_STATUS_CANNOT_DELETE;
- }
- }
-
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
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 - "
+ "(%s)\n",
+ smb_fname_str_dbg(smb_fname),
+ nt_errstr(status)));
+ close_file(req, fsp, NORMAL_CLOSE);
+ return status;
+ }
+
/* The set is across all open files on this dev/inode pair. */
if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
close_file(req, fsp, NORMAL_CLOSE);
} else {
struct smb_Dir *dir_hnd = NULL;
long offset = 0;
- char *dname = NULL;
+ const char *dname = NULL;
+ char *talloced = NULL;
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
status = NT_STATUS_OBJECT_NAME_INVALID;
status = NT_STATUS_NO_SUCH_FILE;
while ((dname = ReadDirName(dir_hnd, &offset,
- &smb_fname->st))) {
+ &smb_fname->st, &talloced))) {
TALLOC_CTX *frame = talloc_stackframe();
if (!is_visible_file(conn, fname_dir, dname,
&smb_fname->st, true)) {
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
/* Quick check for "." and ".." */
if (ISDOT(dname) || ISDOTDOT(dname)) {
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if(!mask_match(dname, fname_mask,
conn->case_sensitive)) {
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
TALLOC_FREE(dir_hnd);
status = NT_STATUS_NO_MEMORY;
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
goto out;
}
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
goto out;
}
status = do_unlink(conn, req, smb_fname, dirtype);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
smb_fname->base_name));
TALLOC_FREE(frame);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
}
TALLOC_FREE(dir_hnd);
}
SMB_OFF_T startpos;
files_struct *fsp;
struct lock_struct lock;
- SMB_STRUCT_STAT st;
SMB_OFF_T size = 0;
START_PROFILE(SMBreadbraw);
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
return;
- }
+ }
}
maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
return;
}
- if (SMB_VFS_FSTAT(fsp, &st) == 0) {
- size = st.st_ex_size;
+ if (fsp_stat(fsp) == 0) {
+ size = fsp->fsp_name->st.st_ex_size;
}
if (startpos >= size) {
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS,ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
END_PROFILE(SMBread);
return;
}
files_struct *fsp, SMB_OFF_T startpos,
size_t smb_maxcnt)
{
- SMB_STRUCT_STAT sbuf;
ssize_t nread = -1;
struct lock_struct lock;
int saved_errno = 0;
- if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ if(fsp_stat(fsp) == -1) {
reply_nterror(req, map_nt_error_from_unix(errno));
return;
}
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS, ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
return;
}
- if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
- || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
+ if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
+ (startpos > fsp->fsp_name->st.st_ex_size)
+ || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
/*
* We already know that we would do a short read, so don't
* try the sendfile() path.
}
if (!CHECK_READ(fsp,req)) {
- reply_doserror(req, ERRDOS,ERRbadaccess);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
END_PROFILE(SMBreadX);
return;
}
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS, ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
return;
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS, ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
END_PROFILE(SMBwriteunlock);
return;
}
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS, ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
END_PROFILE(SMBwrite);
return;
}
}
if (!CHECK_WRITE(fsp)) {
- reply_doserror(req, ERRDOS, ERRbadaccess);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
END_PROFILE(SMBwriteX);
return;
}
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS, ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
END_PROFILE(SMBwriteX);
return;
}
if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
if(errno == EINVAL) {
SMB_OFF_T current_pos = startpos;
- SMB_STRUCT_STAT sbuf;
- if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ if(fsp_stat(fsp) == -1) {
reply_nterror(req,
map_nt_error_from_unix(errno));
END_PROFILE(SMBlseek);
return;
}
- current_pos += sbuf.st_ex_size;
+ current_pos += fsp->fsp_name->st.st_ex_size;
if(current_pos < 0)
res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
}
*/
if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
- reply_doserror(req, ERRDOS, ERRbadfid);
+ reply_nterror(req, NT_STATUS_INVALID_HANDLE);
END_PROFILE(SMBclose);
return;
}
&lock);
if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
- reply_doserror(req, ERRDOS,ERRlock);
+ reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
END_PROFILE(SMBwriteclose);
return;
}
{
connection_struct *conn = req->conn;
files_struct *fsp;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBsplopen);
}
/* Open for exclusive use, write only. */
- status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
+ status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
if (!NT_STATUS_IS_OK(status)) {
file_free(req, fsp);
return;
}
-/****************************************************************************
- Static function used by reply_rmdir to delete an entire directory
- tree recursively. Return True on ok, False on fail.
-****************************************************************************/
-
-static bool recursive_rmdir(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct smb_filename *smb_dname)
-{
- char *dname = NULL;
- bool ret = True;
- long offset = 0;
- SMB_STRUCT_STAT st;
- struct smb_Dir *dir_hnd;
-
- SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
-
- dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
- if(dir_hnd == NULL)
- return False;
-
- while((dname = ReadDirName(dir_hnd, &offset, &st))) {
- struct smb_filename *smb_dname_full = NULL;
- char *fullname = NULL;
- bool do_break = true;
- NTSTATUS status;
-
- if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(dname);
- continue;
- }
-
- if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
- false)) {
- TALLOC_FREE(dname);
- continue;
- }
-
- /* Construct the full name. */
- fullname = talloc_asprintf(ctx,
- "%s/%s",
- smb_dname->base_name,
- dname);
- if (!fullname) {
- errno = ENOMEM;
- goto err_break;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(), fullname,
- NULL, NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
- goto err_break;
- }
-
- if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
- if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
- goto err_break;
- }
- if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
- goto err_break;
- }
- } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- /* Successful iteration. */
- do_break = false;
-
- err_break:
- TALLOC_FREE(smb_dname_full);
- TALLOC_FREE(fullname);
- TALLOC_FREE(dname);
- if (do_break) {
- ret = false;
- break;
- }
- }
- TALLOC_FREE(dir_hnd);
- return ret;
-}
-
-/****************************************************************************
- The internals of the rmdir code - called elsewhere.
-****************************************************************************/
-
-NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
- connection_struct *conn,
- struct smb_filename *smb_dname)
-{
- int ret;
- SMB_STRUCT_STAT st;
-
- SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
-
- /* Might be a symlink. */
- if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
- return map_nt_error_from_unix(errno);
- }
-
- if (S_ISLNK(smb_dname->st.st_ex_mode)) {
- /* Is what it points to a directory ? */
- if(SMB_VFS_STAT(conn, smb_dname) != 0) {
- return map_nt_error_from_unix(errno);
- }
- if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
- return NT_STATUS_NOT_A_DIRECTORY;
- }
- ret = SMB_VFS_UNLINK(conn, smb_dname);
- } else {
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
- }
- if (ret == 0) {
- notify_fname(conn, NOTIFY_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
- return NT_STATUS_OK;
- }
-
- if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
- /*
- * Check to see if the only thing in this directory are
- * vetoed files/directories. If so then delete them and
- * retry. If we fail to delete any of them (and we *don't*
- * do a recursive delete) then fail the rmdir.
- */
- char *dname = NULL;
- long dirpos = 0;
- struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
- smb_dname->base_name, NULL,
- 0);
-
- if(dir_hnd == NULL) {
- errno = ENOTEMPTY;
- goto err;
- }
-
- while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
- TALLOC_FREE(dname);
- continue;
- }
- if (!is_visible_file(conn, smb_dname->base_name, dname,
- &st, false)) {
- TALLOC_FREE(dname);
- continue;
- }
- if(!IS_VETO_PATH(conn, dname)) {
- TALLOC_FREE(dir_hnd);
- TALLOC_FREE(dname);
- errno = ENOTEMPTY;
- goto err;
- }
- TALLOC_FREE(dname);
- }
-
- /* We only have veto files/directories.
- * Are we allowed to delete them ? */
-
- if(!lp_recursive_veto_delete(SNUM(conn))) {
- TALLOC_FREE(dir_hnd);
- errno = ENOTEMPTY;
- goto err;
- }
-
- /* Do a recursive delete. */
- RewindDir(dir_hnd,&dirpos);
- while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
- struct smb_filename *smb_dname_full = NULL;
- char *fullname = NULL;
- bool do_break = true;
- NTSTATUS status;
-
- if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(dname);
- continue;
- }
- if (!is_visible_file(conn, smb_dname->base_name, dname,
- &st, false)) {
- TALLOC_FREE(dname);
- continue;
- }
-
- fullname = talloc_asprintf(ctx,
- "%s/%s",
- smb_dname->base_name,
- dname);
-
- if(!fullname) {
- errno = ENOMEM;
- goto err_break;
- }
-
- status = create_synthetic_smb_fname(talloc_tos(),
- fullname, NULL,
- NULL,
- &smb_dname_full);
- if (!NT_STATUS_IS_OK(status)) {
- errno = map_errno_from_nt_status(status);
- goto err_break;
- }
-
- if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
- goto err_break;
- }
- if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
- if(!recursive_rmdir(ctx, conn,
- smb_dname_full)) {
- goto err_break;
- }
- if(SMB_VFS_RMDIR(conn,
- smb_dname_full->base_name) != 0) {
- goto err_break;
- }
- } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
- goto err_break;
- }
-
- /* Successful iteration. */
- do_break = false;
-
- err_break:
- TALLOC_FREE(fullname);
- TALLOC_FREE(smb_dname_full);
- TALLOC_FREE(dname);
- if (do_break)
- break;
- }
- TALLOC_FREE(dir_hnd);
- /* Retry the rmdir */
- ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
- }
-
- err:
-
- if (ret != 0) {
- DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
- "%s\n", smb_fname_str_dbg(smb_dname),
- strerror(errno)));
- return map_nt_error_from_unix(errno);
- }
-
- notify_fname(conn, NOTIFY_ACTION_REMOVED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- smb_dname->base_name);
-
- return NT_STATUS_OK;
-}
-
/****************************************************************************
Reply to a rmdir.
****************************************************************************/
char *directory = NULL;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
+ files_struct *fsp = NULL;
+ int info = 0;
struct smbd_server_connection *sconn = smbd_server_conn;
START_PROFILE(SMBrmdir);
goto out;
}
- dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
- status = rmdir_internals(ctx, conn, smb_dname);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ smb_dname, /* fname */
+ DELETE_ACCESS, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_OPEN, /* create_disposition*/
+ FILE_DIRECTORY_FILE, /* create_options */
+ FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info); /* pinfo */
+
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(req->mid)) {
+ /* We have re-scheduled this call. */
+ goto out;
+ }
+ reply_nterror(req, status);
+ goto out;
+ }
+
+ status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
if (!NT_STATUS_IS_OK(status)) {
+ close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, status);
goto out;
}
+ if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
+ close_file(req, fsp, ERROR_CLOSE);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
+ goto out;
+ }
+
+ close_file(req, fsp, NORMAL_CLOSE);
reply_outbuf(req, 0, 0);
+ dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
+
DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
out:
TALLOC_FREE(smb_dname);
goto out;
}
- status = can_rename(conn, fsp, attrs, &fsp->fsp_name->st);
+ status = can_rename(conn, fsp, attrs);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
*/
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)) {
/* Note that here we set the *inital* delete on close flag,
int count=0;
NTSTATUS status = NT_STATUS_OK;
struct smb_Dir *dir_hnd = NULL;
- char *dname = NULL;
+ const char *dname = NULL;
+ char *talloced = NULL;
long offset = 0;
int create_options = 0;
bool posix_pathnames = lp_posix_pathnames();
* - gentest fix. JRA
*/
- while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
+ while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
+ &talloced))) {
files_struct *fsp = NULL;
char *destname = NULL;
bool sysdir_entry = False;
if (attrs & aDIR) {
sysdir_entry = True;
} else {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
}
if (!is_visible_file(conn, fname_src_dir, dname,
&smb_fname_src->st, false)) {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
&destname)) {
DEBUG(6, ("resolve_wildcards %s %s failed\n",
smb_fname_src->base_name, destname));
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if (!destname) {
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(dname);
+ TALLOC_FREE(talloced);
}
TALLOC_FREE(dir_hnd);
}
out:
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
TALLOC_FREE(fname_src_dir);
TALLOC_FREE(fname_src_mask);
return status;
}
} else {
struct smb_Dir *dir_hnd = NULL;
- char *dname = NULL;
+ const char *dname = NULL;
+ char *talloced = NULL;
long offset = 0;
/*
/* Iterate over the src dir copying each entry to the dst. */
while ((dname = ReadDirName(dir_hnd, &offset,
- &smb_fname_src->st))) {
+ &smb_fname_src->st, &talloced))) {
char *destname = NULL;
if (ISDOT(dname) || ISDOTDOT(dname)) {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if (!is_visible_file(conn, fname_src_dir, dname,
&smb_fname_src->st, false)) {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if(!mask_match(dname, fname_src_mask,
conn->case_sensitive)) {
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
continue;
}
if (!smb_fname_src->base_name) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(dname);
+ 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(dname);
+ TALLOC_FREE(talloced);
continue;
}
if (!destname) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
status = check_name(conn, smb_fname_src->base_name);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
reply_nterror(req, status);
goto out;
}
status = check_name(conn, smb_fname_dst->base_name);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dir_hnd);
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
reply_nterror(req, status);
goto out;
}
count++;
}
- TALLOC_FREE(dname);
+ TALLOC_FREE(talloced);
}
TALLOC_FREE(dir_hnd);
}
if (type & LOCKING_ANDX_CANCEL_LOCK) {
struct blocking_lock_record *blr = NULL;
+ if (num_locks > 1) {
+ /*
+ * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
+ * if the lock vector contains one entry. When given mutliple cancel
+ * requests in a single PDU we expect the server to return an
+ * error. Windows servers seem to accept the request but only
+ * cancel the first lock.
+ * JRA - Do what Windows does (tm) :-).
+ */
+
+#if 0
+ /* MS-CIFS (2.2.4.32.1) behavior. */
+ return NT_STATUS_DOS(ERRDOS,
+ ERRcancelviolation);
+#else
+ /* Windows behavior. */
+ if (i != 0) {
+ DEBUG(10,("smbd_do_locking: ignoring subsequent "
+ "cancel request\n"));
+ continue;
+ }
+#endif
+ }
+
if (lp_blocking_locks(SNUM(conn))) {
/* Schedule a message to ourselves to
void reply_getattrE(struct smb_request *req)
{
connection_struct *conn = req->conn;
- SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
struct timespec create_ts;
}
/* Do an fstat on this file */
- if(fsp_stat(fsp, &sbuf)) {
+ if(fsp_stat(fsp)) {
reply_nterror(req, map_nt_error_from_unix(errno));
END_PROFILE(SMBgetattrE);
return;
}
- fsp->fsp_name->st = sbuf;
-
mode = dos_mode(conn, fsp->fsp_name);
/*
create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
- convert_timespec_to_time_t(sbuf.st_ex_atime));
+ convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
/* Should we check pending modtime here ? JRA */
srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
- convert_timespec_to_time_t(sbuf.st_ex_mtime));
+ convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
if (mode & aDIR) {
SIVAL(req->outbuf, smb_vwv6, 0);
SIVAL(req->outbuf, smb_vwv8, 0);
} else {
- uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
- SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
+ uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
+ SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
SIVAL(req->outbuf, smb_vwv8, allocation_size);
}
SSVAL(req->outbuf,smb_vwv10, mode);