mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r21191: Add in the POSIX open/mkdir/unlink calls.
Move more error code returns to NTSTATUS. Client test code to follow... See if this passes the build-farm before I add it into 3.0.25. Jeremy.
This commit is contained in:
parent
b10f4cdfc0
commit
83dbbdff34
@ -515,6 +515,7 @@ typedef struct files_struct {
|
||||
BOOL aio_write_behind;
|
||||
BOOL lockdb_clean;
|
||||
BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */
|
||||
BOOL posix_open;
|
||||
char *fsp_name;
|
||||
|
||||
struct vfs_fsp_data *vfs_extension;
|
||||
@ -736,6 +737,8 @@ struct pending_message_list {
|
||||
DATA_BLOB private_data;
|
||||
};
|
||||
|
||||
#define SHARE_MODE_FLAG_POSIX_OPEN 0x1
|
||||
|
||||
/* struct returned by get_share_modes */
|
||||
struct share_mode_entry {
|
||||
struct process_id pid;
|
||||
@ -752,6 +755,7 @@ struct share_mode_entry {
|
||||
SMB_INO_T inode;
|
||||
unsigned long share_file_id;
|
||||
uint32 uid; /* uid of file opener. */
|
||||
uint16 flags; /* POSIX_OPEN only defined so far... */
|
||||
};
|
||||
|
||||
/* oplock break message definition - linearization of share_mode_entry.
|
||||
@ -769,10 +773,11 @@ Offset Data length.
|
||||
36 SMB_INO_T inode 8 bytes
|
||||
44 unsigned long file_id 4 bytes
|
||||
48 uint32 uid 4 bytes
|
||||
52
|
||||
52 uint16 flags 2 bytes
|
||||
54
|
||||
|
||||
*/
|
||||
#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 52
|
||||
#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 54
|
||||
|
||||
struct share_mode_lock {
|
||||
const char *servicepath; /* canonicalized. */
|
||||
@ -1580,19 +1585,19 @@ extern int chain_size;
|
||||
* Note these must fit into 16-bits.
|
||||
*/
|
||||
|
||||
#define NO_OPLOCK 0
|
||||
#define EXCLUSIVE_OPLOCK 1
|
||||
#define BATCH_OPLOCK 2
|
||||
#define LEVEL_II_OPLOCK 4
|
||||
#define NO_OPLOCK 0x0
|
||||
#define EXCLUSIVE_OPLOCK 0x1
|
||||
#define BATCH_OPLOCK 0x2
|
||||
#define LEVEL_II_OPLOCK 0x4
|
||||
|
||||
/* The following are Samba-private. */
|
||||
#define INTERNAL_OPEN_ONLY 8
|
||||
#define FAKE_LEVEL_II_OPLOCK 16 /* Client requested no_oplock, but we have to
|
||||
#define INTERNAL_OPEN_ONLY 0x8
|
||||
#define FAKE_LEVEL_II_OPLOCK 0x10 /* Client requested no_oplock, but we have to
|
||||
* inform potential level2 holders on
|
||||
* write. */
|
||||
#define DEFERRED_OPEN_ENTRY 32
|
||||
#define UNUSED_SHARE_MODE_ENTRY 64
|
||||
#define FORCE_OPLOCK_BREAK_TO_NONE 128
|
||||
#define DEFERRED_OPEN_ENTRY 0x20
|
||||
#define UNUSED_SHARE_MODE_ENTRY 0x40
|
||||
#define FORCE_OPLOCK_BREAK_TO_NONE 0x80
|
||||
|
||||
/* None of the following should ever appear in fsp->oplock_request. */
|
||||
#define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY|DEFERRED_OPEN_ENTRY|UNUSED_SHARE_MODE_ENTRY|FORCE_OPLOCK_BREAK_TO_NONE)
|
||||
|
@ -446,6 +446,13 @@ Offset Size Name
|
||||
/* Only valid for setfileinfo */
|
||||
#define SMB_SET_POSIX_LOCK 0x208
|
||||
|
||||
/* The set info levels for POSIX path operations. */
|
||||
#define SMB_POSIX_PATH_OPEN 0x209
|
||||
#define SMB_POSIX_PATH_UNLINK 0x20A
|
||||
|
||||
#define SMB_QUERY_FILE_UNIX_INFO2 0x20B /* UNIX File Info2 */
|
||||
#define SMB_SET_FILE_UNIX_INFO2 0x20B
|
||||
|
||||
/* Transact 2 Find First levels */
|
||||
#define SMB_FIND_FILE_UNIX 0x202
|
||||
|
||||
@ -477,6 +484,7 @@ Offset Size Name
|
||||
#define CIFS_UNIX_EXTATTR_CAP 0x8 /* for support of chattr
|
||||
(chflags) and lsattr */
|
||||
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x10 /* Use POSIX pathnames on the wire. */
|
||||
#define CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP 0x20 /* We can cope with POSIX open/mkdir/unlink etc. */
|
||||
|
||||
|
||||
#define SMB_QUERY_POSIX_FS_INFO 0x201
|
||||
@ -579,7 +587,7 @@ number of entries sent will be zero.
|
||||
|
||||
#define SMB_POSIX_IGNORE_ACE_ENTRIES 0xFFFF
|
||||
|
||||
/* Definition of SMB_SET_POSIX_LOCK */
|
||||
/* Definition of parameter block of SMB_SET_POSIX_LOCK */
|
||||
/*
|
||||
[2 bytes] lock_type - 0 = Read, 1 = Write, 2 = Unlock
|
||||
[2 bytes] lock_flags - 1 = Wait (only valid for setlock)
|
||||
@ -602,4 +610,37 @@ number of entries sent will be zero.
|
||||
#define POSIX_LOCK_TYPE_WRITE 1
|
||||
#define POSIX_LOCK_TYPE_UNLOCK 2
|
||||
|
||||
/* SMB_POSIX_PATH_OPEN "open_mode" definitions. */
|
||||
#define SMB_O_RDONLY 0x1
|
||||
#define SMB_O_WRONLY 0x2
|
||||
#define SMB_O_RDWR 0x4
|
||||
|
||||
#define SMB_ACCMODE 0x7
|
||||
|
||||
#define SMB_O_CREAT 0x10
|
||||
#define SMB_O_EXCL 0x20
|
||||
#define SMB_O_TRUNC 0x40
|
||||
#define SMB_O_APPEND 0x80
|
||||
#define SMB_O_SYNC 0x100
|
||||
#define SMB_O_DIRECTORY 0x200
|
||||
#define SMB_O_NOFOLLOW 0x400
|
||||
#define SMB_O_DIRECT 0x800
|
||||
|
||||
/* Definition of request parameter block for SMB_POSIX_PATH_OPEN */
|
||||
/*
|
||||
[4 bytes] flags (as smb_ntcreate_Flags).
|
||||
[4 bytes] open_mode
|
||||
[4 bytes] mode_t - same encoding as "Standard UNIX permissions" above.
|
||||
[2 bytes] ret_info_level - optimization. Info level to be returned.
|
||||
*/
|
||||
|
||||
/* Definition of reply data block for SMB_POSIX_PATH_OPEN */
|
||||
|
||||
#define SMB_NO_INFO_LEVEL_RETURNED 0xFFFF
|
||||
|
||||
/*
|
||||
[2 bytes] reply info level - as requested or 0xFFFF if not available.
|
||||
[n bytes] - info level reply - if available.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
@ -154,6 +154,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
|
||||
out->dev = (SMB_DEV_T)in->dev;
|
||||
out->inode = (SMB_INO_T)in->ino;
|
||||
out->uid = (uint32)geteuid();
|
||||
out->flags = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -81,7 +81,7 @@ BOOL is_locked(files_struct *fsp,
|
||||
enum brl_type lock_type)
|
||||
{
|
||||
int strict_locking = lp_strict_locking(fsp->conn->params);
|
||||
enum brl_flavour lock_flav = lp_posix_cifsu_locktype();
|
||||
enum brl_flavour lock_flav = lp_posix_cifsu_locktype(fsp);
|
||||
BOOL ret = True;
|
||||
|
||||
if (count == 0) {
|
||||
@ -426,13 +426,14 @@ char *share_mode_str(int num, struct share_mode_entry *e)
|
||||
slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s "
|
||||
"pid = %s, share_access = 0x%x, private_options = 0x%x, "
|
||||
"access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, "
|
||||
"uid = %u, dev = 0x%x, inode = %.0f",
|
||||
"uid = %u, flags = %u, dev = 0x%x, inode = %.0f",
|
||||
num,
|
||||
e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
|
||||
procid_str_static(&e->pid),
|
||||
e->share_access, e->private_options,
|
||||
e->access_mask, e->op_mid, e->op_type, e->share_file_id,
|
||||
(unsigned int)e->uid, (unsigned int)e->dev, (double)e->inode );
|
||||
(unsigned int)e->uid, (unsigned int)e->flags,
|
||||
(unsigned int)e->dev, (double)e->inode );
|
||||
|
||||
return share_str;
|
||||
}
|
||||
@ -912,6 +913,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
|
||||
e->inode = fsp->inode;
|
||||
e->share_file_id = fsp->fh->file_id;
|
||||
e->uid = (uint32)uid;
|
||||
e->flags = fsp->posix_open ? SHARE_MODE_FLAG_POSIX_OPEN : 0;
|
||||
}
|
||||
|
||||
static void fill_deferred_open_entry(struct share_mode_entry *e,
|
||||
@ -927,6 +929,7 @@ static void fill_deferred_open_entry(struct share_mode_entry *e,
|
||||
e->dev = dev;
|
||||
e->inode = ino;
|
||||
e->uid = (uint32)-1;
|
||||
e->flags = 0;
|
||||
}
|
||||
|
||||
static void add_share_mode_entry(struct share_mode_lock *lck,
|
||||
|
@ -636,7 +636,7 @@ static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
|
||||
to delete all locks on this fsp before this function is called.
|
||||
****************************************************************************/
|
||||
|
||||
int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
|
||||
NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp)
|
||||
{
|
||||
int saved_errno = 0;
|
||||
int ret;
|
||||
@ -651,7 +651,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
|
||||
*/
|
||||
ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
|
||||
fsp->fh->fd = -1;
|
||||
return ret;
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
if (get_windows_lock_ref_count(fsp)) {
|
||||
@ -663,7 +663,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
|
||||
|
||||
add_fd_to_close_entry(fsp);
|
||||
fsp->fh->fd = -1;
|
||||
return 0;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -701,14 +701,18 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp)
|
||||
|
||||
ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
|
||||
|
||||
if (saved_errno != 0) {
|
||||
if (ret == 0 && saved_errno != 0) {
|
||||
errno = saved_errno;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
fsp->fh->fd = -1;
|
||||
|
||||
return ret;
|
||||
if (ret == -1) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -5589,17 +5589,23 @@ void lp_set_posix_pathnames(void)
|
||||
Global state for POSIX lock processing - CIFS unix extensions.
|
||||
********************************************************************/
|
||||
|
||||
BOOL posix_default_lock_was_set;
|
||||
static enum brl_flavour posix_cifsx_locktype; /* By default 0 == WINDOWS_LOCK */
|
||||
|
||||
enum brl_flavour lp_posix_cifsu_locktype(void)
|
||||
enum brl_flavour lp_posix_cifsu_locktype(files_struct *fsp)
|
||||
{
|
||||
return posix_cifsx_locktype;
|
||||
if (posix_default_lock_was_set) {
|
||||
return posix_cifsx_locktype;
|
||||
} else {
|
||||
return fsp->posix_open ? POSIX_LOCK : WINDOWS_LOCK;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
********************************************************************/
|
||||
|
||||
void lp_set_posix_cifsx_locktype(enum brl_flavour val)
|
||||
void lp_set_posix_default_cifsx_readwrite_locktype(enum brl_flavour val)
|
||||
{
|
||||
posix_default_lock_was_set = True;
|
||||
posix_cifsx_locktype = val;
|
||||
}
|
||||
|
@ -2081,6 +2081,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
0,
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
NULL, &fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
@ -2187,6 +2188,7 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecur
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
0,
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
NULL, &fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
Unix SMB/CIFS implementation.
|
||||
file closing
|
||||
Copyright (C) Andrew Tridgell 1992-1998
|
||||
Copyright (C) Jeremy Allison 1992-2004.
|
||||
Copyright (C) Jeremy Allison 1992-2007.
|
||||
Copyright (C) Volker Lendecke 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -90,22 +90,21 @@ static void check_magic(files_struct *fsp,connection_struct *conn)
|
||||
Common code to close a file or a directory.
|
||||
****************************************************************************/
|
||||
|
||||
static int close_filestruct(files_struct *fsp)
|
||||
static NTSTATUS close_filestruct(files_struct *fsp)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
connection_struct *conn = fsp->conn;
|
||||
int ret = 0;
|
||||
|
||||
if (fsp->fh->fd != -1) {
|
||||
if(flush_write_cache(fsp, CLOSE_FLUSH) == -1)
|
||||
ret = -1;
|
||||
|
||||
if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
}
|
||||
delete_write_cache(fsp);
|
||||
}
|
||||
|
||||
conn->num_files_open--;
|
||||
SAFE_FREE(fsp->wbmpx_ptr);
|
||||
|
||||
return ret;
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -195,9 +194,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
|
||||
if (delete_file) {
|
||||
int i;
|
||||
/* See if others still have the file open. If this is the
|
||||
* case, then don't delete */
|
||||
* case, then don't delete. If all opens are POSIX delete now. */
|
||||
for (i=0; i<lck->num_share_modes; i++) {
|
||||
if (is_valid_share_mode_entry(&lck->share_modes[i])) {
|
||||
struct share_mode_entry *e = &lck->share_modes[i];
|
||||
if (is_valid_share_mode_entry(e)) {
|
||||
if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
|
||||
continue;
|
||||
}
|
||||
delete_file = False;
|
||||
break;
|
||||
}
|
||||
@ -282,12 +285,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
|
||||
fsp->fsp_name, strerror(errno) ));
|
||||
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = NT_STATUS_FILE_DELETED;
|
||||
|
||||
done:
|
||||
|
||||
/* unbecome user. */
|
||||
pop_sec_ctx();
|
||||
|
||||
@ -303,12 +304,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
|
||||
delete on close is done on normal and shutdown close.
|
||||
****************************************************************************/
|
||||
|
||||
static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
NTSTATUS saved_status1 = NT_STATUS_OK;
|
||||
NTSTATUS saved_status2 = NT_STATUS_OK;
|
||||
NTSTATUS saved_status3 = NT_STATUS_OK;
|
||||
connection_struct *conn = fsp->conn;
|
||||
int saved_errno = 0;
|
||||
int err = 0;
|
||||
int err1 = 0;
|
||||
|
||||
if (fsp->aio_write_behind) {
|
||||
/*
|
||||
@ -317,8 +319,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
*/
|
||||
int ret = wait_for_aio_completion(fsp);
|
||||
if (ret) {
|
||||
saved_errno = ret;
|
||||
err1 = -1;
|
||||
saved_status1 = map_nt_error_from_unix(ret);
|
||||
}
|
||||
} else {
|
||||
cancel_aio_by_fsp(fsp);
|
||||
@ -329,15 +330,12 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
* error here, we must remember this.
|
||||
*/
|
||||
|
||||
if (close_filestruct(fsp) == -1) {
|
||||
saved_errno = errno;
|
||||
err1 = -1;
|
||||
}
|
||||
saved_status2 = close_filestruct(fsp);
|
||||
|
||||
if (fsp->print_file) {
|
||||
print_fsp_end(fsp, close_type);
|
||||
file_free(fsp);
|
||||
return 0;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* If this is an old DOS or FCB open and we have multiple opens on
|
||||
@ -346,7 +344,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
|
||||
if (fsp->fh->ref_count == 1) {
|
||||
/* Should we return on error here... ? */
|
||||
close_remove_share_mode(fsp, close_type);
|
||||
saved_status3 = close_remove_share_mode(fsp, close_type);
|
||||
}
|
||||
|
||||
if(fsp->oplock_type) {
|
||||
@ -355,13 +353,7 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
|
||||
locking_close_file(fsp);
|
||||
|
||||
err = fd_close(conn, fsp);
|
||||
|
||||
/* Only save errno if fd_close failed and we don't already
|
||||
have an errno saved from a flush call. */
|
||||
if ((err1 != -1) && (err == -1)) {
|
||||
saved_errno = errno;
|
||||
}
|
||||
status = fd_close(conn, fsp);
|
||||
|
||||
/* check for magic scripts */
|
||||
if (close_type == NORMAL_CLOSE) {
|
||||
@ -378,29 +370,34 @@ static int close_normal_file(files_struct *fsp, enum file_close_type close_type)
|
||||
set_filetime(conn, fsp->fsp_name, fsp->last_write_time);
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
if (!NT_STATUS_IS_OK(saved_status1)) {
|
||||
status = saved_status1;
|
||||
} else if (!NT_STATUS_IS_OK(saved_status2)) {
|
||||
status = saved_status2;
|
||||
} else if (!NT_STATUS_IS_OK(saved_status3)) {
|
||||
status = saved_status3;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
|
||||
conn->user,fsp->fsp_name,
|
||||
conn->num_files_open,
|
||||
(err == -1 || err1 == -1) ? strerror(saved_errno) : ""));
|
||||
nt_errstr(status) ));
|
||||
|
||||
file_free(fsp);
|
||||
|
||||
if (err == -1 || err1 == -1) {
|
||||
errno = saved_errno;
|
||||
return saved_errno;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Close a directory opened by an NT SMB call.
|
||||
****************************************************************************/
|
||||
|
||||
static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
{
|
||||
struct share_mode_lock *lck = 0;
|
||||
BOOL delete_dir = False;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
/*
|
||||
* NT can set delete_on_close of the last open
|
||||
@ -411,7 +408,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
|
||||
if (lck == NULL) {
|
||||
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
|
||||
return EINVAL;
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!del_share_mode(lck, fsp)) {
|
||||
@ -441,9 +438,13 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
if (delete_dir) {
|
||||
int i;
|
||||
/* See if others still have the dir open. If this is the
|
||||
* case, then don't delete */
|
||||
* case, then don't delete. If all opens are POSIX delete now. */
|
||||
for (i=0; i<lck->num_share_modes; i++) {
|
||||
if (is_valid_share_mode_entry(&lck->share_modes[i])) {
|
||||
struct share_mode_entry *e = &lck->share_modes[i];
|
||||
if (is_valid_share_mode_entry(e)) {
|
||||
if (fsp->posix_open && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
|
||||
continue;
|
||||
}
|
||||
delete_dir = False;
|
||||
break;
|
||||
}
|
||||
@ -469,7 +470,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
|
||||
TALLOC_FREE(lck);
|
||||
|
||||
ok = rmdir_internals(fsp->conn, fsp->fsp_name);
|
||||
status = rmdir_internals(fsp->conn, fsp->fsp_name);
|
||||
|
||||
DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
|
||||
fsp->fsp_name, ok ? "succeeded" : "failed" ));
|
||||
@ -482,7 +483,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
* now fail as the directory has been deleted.
|
||||
*/
|
||||
|
||||
if(ok) {
|
||||
if(NT_STATUS_IS_OK(status)) {
|
||||
remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
|
||||
}
|
||||
} else {
|
||||
@ -496,35 +497,35 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
|
||||
*/
|
||||
close_filestruct(fsp);
|
||||
file_free(fsp);
|
||||
return 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Close a 'stat file' opened internally.
|
||||
****************************************************************************/
|
||||
|
||||
static int close_stat(files_struct *fsp)
|
||||
NTSTATUS close_stat(files_struct *fsp)
|
||||
{
|
||||
/*
|
||||
* Do the code common to files and directories.
|
||||
*/
|
||||
close_filestruct(fsp);
|
||||
file_free(fsp);
|
||||
return 0;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Close a files_struct.
|
||||
****************************************************************************/
|
||||
|
||||
int close_file(files_struct *fsp, enum file_close_type close_type)
|
||||
NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type)
|
||||
{
|
||||
if(fsp->is_directory)
|
||||
if(fsp->is_directory) {
|
||||
return close_directory(fsp, close_type);
|
||||
else if (fsp->is_stat)
|
||||
} else if (fsp->is_stat) {
|
||||
return close_stat(fsp);
|
||||
else if (fsp->fake_file_handle != NULL)
|
||||
} else if (fsp->fake_file_handle != NULL) {
|
||||
return close_fake_file(fsp);
|
||||
else
|
||||
return close_normal_file(fsp, close_type);
|
||||
}
|
||||
return close_normal_file(fsp, close_type);
|
||||
}
|
||||
|
@ -884,6 +884,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
0, /* no create options. */
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
NULL, &fsp);
|
||||
} else {
|
||||
status = open_file_stat(conn, name, pst, &fsp);
|
||||
|
@ -160,8 +160,8 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
|
||||
(*fh) = NULL;
|
||||
}
|
||||
|
||||
int close_fake_file(files_struct *fsp)
|
||||
NTSTATUS close_fake_file(files_struct *fsp)
|
||||
{
|
||||
file_free(fsp);
|
||||
return 0;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
@ -281,10 +281,10 @@ static BOOL saved_short_case_preserve;
|
||||
Save case semantics.
|
||||
****************************************************************************/
|
||||
|
||||
static void set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
|
||||
static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
|
||||
{
|
||||
if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
|
||||
return;
|
||||
return file_attributes;
|
||||
}
|
||||
|
||||
saved_case_sensitive = conn->case_sensitive;
|
||||
@ -295,6 +295,8 @@ static void set_posix_case_semantics(connection_struct *conn, uint32 file_attrib
|
||||
conn->case_sensitive = True;
|
||||
conn->case_preserve = True;
|
||||
conn->short_case_preserve = True;
|
||||
|
||||
return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -455,6 +457,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
|
||||
uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
|
||||
uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
|
||||
uint32 new_file_attributes;
|
||||
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
|
||||
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
|
||||
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
|
||||
@ -625,7 +628,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
* Check if POSIX semantics are wanted.
|
||||
*/
|
||||
|
||||
set_posix_case_semantics(conn, file_attributes);
|
||||
new_file_attributes = set_posix_case_semantics(conn, file_attributes);
|
||||
|
||||
status = unix_convert(conn, fname, False, NULL, &sbuf);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -679,6 +682,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
new_file_attributes,
|
||||
&info, &fsp);
|
||||
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
@ -714,7 +718,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
file_attributes,
|
||||
new_file_attributes,
|
||||
oplock_request,
|
||||
&info, &fsp);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -756,6 +760,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
new_file_attributes,
|
||||
&info, &fsp);
|
||||
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
@ -1096,6 +1101,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
uint32 flags;
|
||||
uint32 access_mask;
|
||||
uint32 file_attributes;
|
||||
uint32 new_file_attributes;
|
||||
uint32 share_access;
|
||||
uint32 create_disposition;
|
||||
uint32 create_options;
|
||||
@ -1252,7 +1258,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
* Check if POSIX semantics are wanted.
|
||||
*/
|
||||
|
||||
set_posix_case_semantics(conn, file_attributes);
|
||||
new_file_attributes = set_posix_case_semantics(conn, file_attributes);
|
||||
|
||||
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
|
||||
|
||||
@ -1324,6 +1330,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
new_file_attributes,
|
||||
&info, &fsp);
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
@ -1341,7 +1348,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
file_attributes,
|
||||
new_file_attributes,
|
||||
oplock_request,
|
||||
&info, &fsp);
|
||||
|
||||
@ -1364,6 +1371,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
share_access,
|
||||
create_disposition,
|
||||
create_options,
|
||||
new_file_attributes,
|
||||
&info, &fsp);
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
@ -1570,7 +1578,6 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
uint32 fattr;
|
||||
int info;
|
||||
SMB_OFF_T ret=-1;
|
||||
int close_ret;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
|
||||
ZERO_STRUCT(sbuf1);
|
||||
@ -1670,7 +1677,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
/* Ensure the modtime is set correctly on the destination file. */
|
||||
fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
|
||||
|
||||
close_ret = close_file(fsp2,NORMAL_CLOSE);
|
||||
status = close_file(fsp2,NORMAL_CLOSE);
|
||||
|
||||
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
|
||||
creates the file. This isn't the correct thing to do in the copy
|
||||
@ -1682,8 +1689,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
return NT_STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
if (close_ret != 0) {
|
||||
status = map_nt_error_from_unix(close_ret);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
|
||||
nt_errstr(status), oldname, newname));
|
||||
}
|
||||
|
@ -67,14 +67,13 @@ static BOOL fd_open(struct connection_struct *conn,
|
||||
Close the file associated with a fsp.
|
||||
****************************************************************************/
|
||||
|
||||
int fd_close(struct connection_struct *conn,
|
||||
files_struct *fsp)
|
||||
NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp)
|
||||
{
|
||||
if (fsp->fh->fd == -1) {
|
||||
return 0; /* What we used to call a stat open. */
|
||||
return NT_STATUS_OK; /* What we used to call a stat open. */
|
||||
}
|
||||
if (fsp->fh->ref_count > 1) {
|
||||
return 0; /* Shared handle. Only close last reference. */
|
||||
return NT_STATUS_OK; /* Shared handle. Only close last reference. */
|
||||
}
|
||||
return fd_close_posix(conn, fsp);
|
||||
}
|
||||
@ -1118,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
int flags2=0;
|
||||
BOOL file_existed = VALID_STAT(*psbuf);
|
||||
BOOL def_acl = False;
|
||||
BOOL posix_open = False;
|
||||
SMB_DEV_T dev = 0;
|
||||
SMB_INO_T inode = 0;
|
||||
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
|
||||
@ -1156,10 +1156,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* We add aARCH to this as this mode is only used if the file is
|
||||
* created new. */
|
||||
unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname,
|
||||
parent_dir);
|
||||
if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) {
|
||||
posix_open = True;
|
||||
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
|
||||
* created new. */
|
||||
unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname,
|
||||
parent_dir);
|
||||
}
|
||||
|
||||
DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
|
||||
"access_mask=0x%x share_access=0x%x "
|
||||
@ -1197,9 +1203,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
return status;
|
||||
}
|
||||
|
||||
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
|
||||
if (file_existed) {
|
||||
existing_dos_attributes = dos_mode(conn, fname, psbuf);
|
||||
if (!posix_open) {
|
||||
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
|
||||
if (file_existed) {
|
||||
existing_dos_attributes = dos_mode(conn, fname, psbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* ignore any oplock requests if oplocks are disabled */
|
||||
@ -1294,7 +1302,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
/* We only care about matching attributes on file exists and
|
||||
* overwrite. */
|
||||
|
||||
if (file_existed && ((create_disposition == FILE_OVERWRITE) ||
|
||||
if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) ||
|
||||
(create_disposition == FILE_OVERWRITE_IF))) {
|
||||
if (!open_match_attributes(conn, fname,
|
||||
existing_dos_attributes,
|
||||
@ -1359,7 +1367,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
}
|
||||
#endif /* O_SYNC */
|
||||
|
||||
if (!CAN_WRITE(conn)) {
|
||||
if (posix_open & (access_mask & FILE_APPEND_DATA)) {
|
||||
flags2 |= O_APPEND;
|
||||
}
|
||||
|
||||
if (!posix_open && !CAN_WRITE(conn)) {
|
||||
/*
|
||||
* We should really return a permission denied error if either
|
||||
* O_CREAT or O_TRUNC are set, but for compatibility with
|
||||
@ -1393,6 +1405,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
fsp->access_mask = open_access_mask; /* We change this to the
|
||||
* requested access_mask after
|
||||
* the open is done. */
|
||||
fsp->posix_open = posix_open;
|
||||
|
||||
/* Ensure no SAMBA_PRIVATE bits can be set. */
|
||||
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
|
||||
|
||||
@ -1769,9 +1783,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
/* Files should be initially set as archive */
|
||||
if (lp_map_archive(SNUM(conn)) ||
|
||||
lp_store_dos_attributes(SNUM(conn))) {
|
||||
file_set_dosmode(conn, fname,
|
||||
if (!posix_open) {
|
||||
file_set_dosmode(conn, fname,
|
||||
new_dos_attributes | aARCH, NULL,
|
||||
parent_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1780,7 +1796,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
|
||||
* selected.
|
||||
*/
|
||||
|
||||
if (!file_existed && !def_acl) {
|
||||
if (!posix_open && !file_existed && !def_acl) {
|
||||
|
||||
int saved_errno = errno; /* We might get ENOSYS in the next
|
||||
* call.. */
|
||||
@ -1873,15 +1889,17 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
|
||||
Close the fchmod file fd - ensure no locks are lost.
|
||||
****************************************************************************/
|
||||
|
||||
int close_file_fchmod(files_struct *fsp)
|
||||
NTSTATUS close_file_fchmod(files_struct *fsp)
|
||||
{
|
||||
int ret = fd_close(fsp->conn, fsp);
|
||||
NTSTATUS status = fd_close(fsp->conn, fsp);
|
||||
file_free(fsp);
|
||||
return ret;
|
||||
return status;
|
||||
}
|
||||
|
||||
static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
|
||||
SMB_STRUCT_STAT *psbuf)
|
||||
static NTSTATUS mkdir_internal(connection_struct *conn,
|
||||
const char *name,
|
||||
uint32 file_attributes,
|
||||
SMB_STRUCT_STAT *psbuf)
|
||||
{
|
||||
int ret= -1;
|
||||
mode_t mode;
|
||||
@ -1905,7 +1923,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
mode = unix_mode(conn, aDIR, name, parent_dir);
|
||||
if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
|
||||
mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
|
||||
} else {
|
||||
mode = unix_mode(conn, aDIR, name, parent_dir);
|
||||
}
|
||||
|
||||
if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
@ -1930,15 +1952,17 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
|
||||
inherit_access_acl(conn, parent_dir, name, mode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if high bits should have been set,
|
||||
* then (if bits are missing): add them.
|
||||
* Consider bits automagically set by UNIX, i.e. SGID bit from parent
|
||||
* dir.
|
||||
*/
|
||||
if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
|
||||
SMB_VFS_CHMOD(conn, name,
|
||||
psbuf->st_mode | (mode & ~psbuf->st_mode));
|
||||
if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
|
||||
/*
|
||||
* Check if high bits should have been set,
|
||||
* then (if bits are missing): add them.
|
||||
* Consider bits automagically set by UNIX, i.e. SGID bit from parent
|
||||
* dir.
|
||||
*/
|
||||
if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
|
||||
SMB_VFS_CHMOD(conn, name,
|
||||
psbuf->st_mode | (mode & ~psbuf->st_mode));
|
||||
}
|
||||
}
|
||||
|
||||
/* Change the owner if required. */
|
||||
@ -1963,6 +1987,7 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
uint32 share_access,
|
||||
uint32 create_disposition,
|
||||
uint32 create_options,
|
||||
uint32 file_attributes,
|
||||
int *pinfo,
|
||||
files_struct **result)
|
||||
{
|
||||
@ -1974,12 +1999,13 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
|
||||
DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
|
||||
"share_access = 0x%x create_options = 0x%x, "
|
||||
"create_disposition = 0x%x\n",
|
||||
"create_disposition = 0x%x, file_attributes = 0x%x\n",
|
||||
fname,
|
||||
(unsigned int)access_mask,
|
||||
(unsigned int)share_access,
|
||||
(unsigned int)create_options,
|
||||
(unsigned int)create_disposition));
|
||||
(unsigned int)create_disposition,
|
||||
(unsigned int)file_attributes));
|
||||
|
||||
if (is_ntfs_stream_name(fname)) {
|
||||
DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
|
||||
@ -2006,7 +2032,11 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
/* If directory exists error. If directory doesn't
|
||||
* exist create. */
|
||||
|
||||
status = mkdir_internal(conn, fname, psbuf);
|
||||
status = mkdir_internal(conn,
|
||||
fname,
|
||||
file_attributes,
|
||||
psbuf);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(2, ("open_directory: unable to create "
|
||||
"%s. Error was %s\n", fname,
|
||||
@ -2023,7 +2053,10 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
* exist create.
|
||||
*/
|
||||
|
||||
status = mkdir_internal(conn, fname, psbuf);
|
||||
status = mkdir_internal(conn,
|
||||
fname,
|
||||
file_attributes,
|
||||
psbuf);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
info = FILE_WAS_CREATED;
|
||||
@ -2081,6 +2114,8 @@ NTSTATUS open_directory(connection_struct *conn,
|
||||
fsp->sent_oplock_break = NO_BREAK_SENT;
|
||||
fsp->is_directory = True;
|
||||
fsp->is_stat = False;
|
||||
fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
|
||||
|
||||
string_set(&fsp->fsp_name,fname);
|
||||
|
||||
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode,
|
||||
@ -2145,7 +2180,11 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory)
|
||||
status = open_directory(conn, directory, &sbuf,
|
||||
FILE_READ_ATTRIBUTES, /* Just a stat open */
|
||||
FILE_SHARE_NONE, /* Ignored for stat opens */
|
||||
FILE_CREATE, 0, NULL, &fsp);
|
||||
FILE_CREATE,
|
||||
0,
|
||||
FILE_ATTRIBUTE_DIRECTORY,
|
||||
NULL,
|
||||
&fsp);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
close_file(fsp, NORMAL_CLOSE);
|
||||
|
@ -832,6 +832,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
|
||||
SINO_T_VAL(msg,36,e->inode);
|
||||
SIVAL(msg,44,e->share_file_id);
|
||||
SIVAL(msg,48,e->uid);
|
||||
SSVAL(msg,52,e->flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -852,6 +853,7 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
|
||||
e->inode = INO_T_VAL(msg,36);
|
||||
e->share_file_id = (unsigned long)IVAL(msg,44);
|
||||
e->uid = (uint32)IVAL(msg,48);
|
||||
e->flags = (uint16)SVAL(msg,52);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -3108,9 +3108,9 @@ int reply_exit(connection_struct *conn,
|
||||
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
int dum_buffsize)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
int outsize = 0;
|
||||
time_t mtime;
|
||||
int32 eclass = 0, err = 0;
|
||||
files_struct *fsp = NULL;
|
||||
START_PROFILE(SMBclose);
|
||||
|
||||
@ -3138,12 +3138,11 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
* Special case - close NT SMB directory handle.
|
||||
*/
|
||||
DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
|
||||
close_file(fsp,NORMAL_CLOSE);
|
||||
status = close_file(fsp,NORMAL_CLOSE);
|
||||
} else {
|
||||
/*
|
||||
* Close ordinary file.
|
||||
*/
|
||||
int close_err;
|
||||
|
||||
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
|
||||
fsp->fh->fd, fsp->fnum,
|
||||
@ -3162,17 +3161,12 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
* a disk full error. If not then it was probably an I/O error.
|
||||
*/
|
||||
|
||||
if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) {
|
||||
errno = close_err;
|
||||
END_PROFILE(SMBclose);
|
||||
return (UNIXERROR(ERRHRD,ERRgeneral));
|
||||
}
|
||||
status = close_file(fsp,NORMAL_CLOSE);
|
||||
}
|
||||
|
||||
/* We have a cached error */
|
||||
if(eclass || err) {
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBclose);
|
||||
return ERROR_DOS(eclass,err);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
END_PROFILE(SMBclose);
|
||||
@ -3189,7 +3183,7 @@ int reply_writeclose(connection_struct *conn,
|
||||
size_t numtowrite;
|
||||
ssize_t nwritten = -1;
|
||||
int outsize = 0;
|
||||
int close_err = 0;
|
||||
NTSTATUS close_status = NT_STATUS_OK;
|
||||
SMB_OFF_T startpos;
|
||||
char *data;
|
||||
time_t mtime;
|
||||
@ -3223,7 +3217,7 @@ int reply_writeclose(connection_struct *conn,
|
||||
if (numtowrite) {
|
||||
DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
|
||||
fsp->fsp_name ));
|
||||
close_err = close_file(fsp,NORMAL_CLOSE);
|
||||
close_status = close_file(fsp,NORMAL_CLOSE);
|
||||
}
|
||||
|
||||
DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
|
||||
@ -3235,10 +3229,9 @@ int reply_writeclose(connection_struct *conn,
|
||||
return(UNIXERROR(ERRHRD,ERRdiskfull));
|
||||
}
|
||||
|
||||
if(close_err != 0) {
|
||||
errno = close_err;
|
||||
if(!NT_STATUS_IS_OK(close_status)) {
|
||||
END_PROFILE(SMBwriteclose);
|
||||
return(UNIXERROR(ERRHRD,ERRgeneral));
|
||||
return ERROR_NT(close_status);
|
||||
}
|
||||
|
||||
outsize = set_message(outbuf,1,0,True);
|
||||
@ -3455,7 +3448,7 @@ int reply_printclose(connection_struct *conn,
|
||||
{
|
||||
int outsize = set_message(outbuf,0,0,False);
|
||||
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
|
||||
int close_err = 0;
|
||||
NTSTATUS status;
|
||||
START_PROFILE(SMBsplclose);
|
||||
|
||||
CHECK_FSP(fsp,conn);
|
||||
@ -3468,12 +3461,11 @@ int reply_printclose(connection_struct *conn,
|
||||
DEBUG(3,("printclose fd=%d fnum=%d\n",
|
||||
fsp->fh->fd,fsp->fnum));
|
||||
|
||||
close_err = close_file(fsp,NORMAL_CLOSE);
|
||||
status = close_file(fsp,NORMAL_CLOSE);
|
||||
|
||||
if(close_err != 0) {
|
||||
errno = close_err;
|
||||
if(!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBsplclose);
|
||||
return(UNIXERROR(ERRHRD,ERRgeneral));
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
END_PROFILE(SMBsplclose);
|
||||
@ -3707,7 +3699,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
|
||||
The internals of the rmdir code - called elsewhere.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL rmdir_internals(connection_struct *conn, const char *directory)
|
||||
NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
|
||||
{
|
||||
int ret;
|
||||
SMB_STRUCT_STAT st;
|
||||
@ -3717,7 +3709,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory)
|
||||
notify_fname(conn, NOTIFY_ACTION_REMOVED,
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
directory);
|
||||
return True;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
|
||||
@ -3791,14 +3783,14 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory)
|
||||
if (ret != 0) {
|
||||
DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
|
||||
"%s\n", directory,strerror(errno)));
|
||||
return False;
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
notify_fname(conn, NOTIFY_ACTION_REMOVED,
|
||||
FILE_NOTIFY_CHANGE_DIR_NAME,
|
||||
directory);
|
||||
|
||||
return True;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -3834,9 +3826,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
||||
}
|
||||
|
||||
dptr_closepath(directory,SVAL(inbuf,smb_pid));
|
||||
if (!rmdir_internals(conn, directory)) {
|
||||
status = rmdir_internals(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBrmdir);
|
||||
return UNIXERROR(ERRDOS, ERRbadpath);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
outsize = set_message(outbuf,0,0,False);
|
||||
@ -4585,7 +4578,6 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
|
||||
uint32 dosattrs;
|
||||
uint32 new_create_disposition;
|
||||
NTSTATUS status;
|
||||
int close_err;
|
||||
|
||||
pstrcpy(dest,dest1);
|
||||
if (target_is_directory) {
|
||||
@ -4670,10 +4662,10 @@ NTSTATUS copy_file(char *src, char *dest1,connection_struct *conn, int ofun,
|
||||
* Thus we don't look at the error return from the
|
||||
* close of fsp1.
|
||||
*/
|
||||
close_err = close_file(fsp2,NORMAL_CLOSE);
|
||||
status = close_file(fsp2,NORMAL_CLOSE);
|
||||
|
||||
if (close_err != 0) {
|
||||
return map_nt_error_from_unix(close_err);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ret != (SMB_OFF_T)src_sbuf.st_size) {
|
||||
|
@ -2529,7 +2529,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
|
||||
SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
|
||||
CIFS_UNIX_POSIX_ACLS_CAP|
|
||||
CIFS_UNIX_POSIX_PATHNAMES_CAP|
|
||||
CIFS_UNIX_FCNTL_LOCKS_CAP)));
|
||||
CIFS_UNIX_FCNTL_LOCKS_CAP|
|
||||
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
|
||||
break;
|
||||
|
||||
case SMB_QUERY_POSIX_FS_INFO:
|
||||
@ -2646,8 +2647,14 @@ cap_low = 0x%x, cap_high = 0x%x\n",
|
||||
mangle_change_to_posix();
|
||||
}
|
||||
|
||||
if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
|
||||
lp_set_posix_cifsx_locktype(POSIX_LOCK);
|
||||
if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
|
||||
!(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
|
||||
/* Client that knows how to do posix locks,
|
||||
* but not posix open/mkdir operations. Set a
|
||||
* default type for read/write checks. */
|
||||
|
||||
lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4845,6 +4852,246 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
tvs);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Create a directory with POSIX semantics.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS smb_posix_mkdir(connection_struct *conn,
|
||||
const char *pdata,
|
||||
int total_data,
|
||||
const char *fname)
|
||||
{
|
||||
NTSTATUS status;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
uint32 raw_unixmode;
|
||||
uint32 mod_unixmode;
|
||||
mode_t unixmode;
|
||||
files_struct *fsp;
|
||||
|
||||
if (total_data < 10) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(sbuf);
|
||||
|
||||
raw_unixmode = IVAL(pdata,8);
|
||||
status = unix_perms_from_wire(conn, &sbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
|
||||
|
||||
status = open_directory(conn,
|
||||
fname,
|
||||
&sbuf,
|
||||
FILE_READ_ATTRIBUTES, /* Just a stat open */
|
||||
FILE_SHARE_NONE, /* Ignored for stat opens */
|
||||
FILE_CREATE,
|
||||
0,
|
||||
mod_unixmode,
|
||||
NULL,
|
||||
&fsp);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
close_file(fsp, NORMAL_CLOSE);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Open/Create a file with POSIX semantics.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS smb_posix_open(connection_struct *conn,
|
||||
char **ppdata,
|
||||
int total_data,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf,
|
||||
int *pdata_return_size)
|
||||
{
|
||||
BOOL extended_oplock_granted = False;
|
||||
const char *pdata = *ppdata;
|
||||
uint32 flags = 0;
|
||||
uint32 wire_open_mode = 0;
|
||||
uint32 raw_unixmode = 0;
|
||||
uint32 mod_unixmode = 0;
|
||||
uint32 create_disp = 0;
|
||||
uint32 access_mask = 0;
|
||||
uint32 create_options = 0;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
mode_t unixmode = (mode_t)0;
|
||||
files_struct *fsp = NULL;
|
||||
int oplock_request = 0;
|
||||
int info = 0;
|
||||
|
||||
if (total_data < 14) {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
flags = IVAL(pdata,0);
|
||||
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
|
||||
if (oplock_request) {
|
||||
oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
|
||||
}
|
||||
|
||||
wire_open_mode = IVAL(pdata,4);
|
||||
|
||||
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
|
||||
return smb_posix_mkdir(conn, pdata, total_data, fname);
|
||||
}
|
||||
|
||||
switch (wire_open_mode & SMB_ACCMODE) {
|
||||
case SMB_O_RDONLY:
|
||||
access_mask = FILE_READ_DATA;
|
||||
break;
|
||||
case SMB_O_WRONLY:
|
||||
access_mask = FILE_WRITE_DATA;
|
||||
break;
|
||||
case SMB_O_RDWR:
|
||||
access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
|
||||
break;
|
||||
default:
|
||||
DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
|
||||
(unsigned int)wire_open_mode ));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
wire_open_mode &= ~SMB_ACCMODE;
|
||||
|
||||
if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
|
||||
create_disp = FILE_CREATE;
|
||||
} else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
|
||||
create_disp = FILE_OVERWRITE_IF;
|
||||
} else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
|
||||
create_disp = FILE_OPEN_IF;
|
||||
} else {
|
||||
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
|
||||
(unsigned int)wire_open_mode ));
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
raw_unixmode = IVAL(pdata,8);
|
||||
status = unix_perms_from_wire(conn,
|
||||
psbuf,
|
||||
raw_unixmode,
|
||||
VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
|
||||
&unixmode);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
|
||||
|
||||
if (wire_open_mode & SMB_O_SYNC) {
|
||||
create_options |= FILE_WRITE_THROUGH;
|
||||
}
|
||||
if (wire_open_mode & SMB_O_APPEND) {
|
||||
access_mask |= FILE_APPEND_DATA;
|
||||
}
|
||||
if (wire_open_mode & SMB_O_DIRECT) {
|
||||
mod_unixmode |= FILE_FLAG_NO_BUFFERING;
|
||||
}
|
||||
|
||||
status = open_file_ntcreate(conn,
|
||||
fname,
|
||||
psbuf,
|
||||
access_mask,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
create_disp,
|
||||
0, /* no create options yet. */
|
||||
mod_unixmode,
|
||||
oplock_request,
|
||||
&info,
|
||||
&fsp);
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
|
||||
extended_oplock_granted = True;
|
||||
}
|
||||
|
||||
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
|
||||
extended_oplock_granted = True;
|
||||
}
|
||||
|
||||
*pdata_return_size = 6;
|
||||
/* Realloc the data size */
|
||||
*ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
|
||||
if (*ppdata == NULL) {
|
||||
close_file(fsp,ERROR_CLOSE);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (extended_oplock_granted) {
|
||||
if (flags & REQUEST_BATCH_OPLOCK) {
|
||||
SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
|
||||
} else {
|
||||
SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
|
||||
}
|
||||
} else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
|
||||
SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
|
||||
} else {
|
||||
SSVAL(pdata,0,NO_OPLOCK_RETURN);
|
||||
}
|
||||
|
||||
SSVAL(pdata,2,fsp->fnum);
|
||||
SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Delete a file with POSIX semantics.
|
||||
****************************************************************************/
|
||||
|
||||
static NTSTATUS smb_posix_unlink(connection_struct *conn,
|
||||
const char *pdata,
|
||||
int total_data,
|
||||
const char *fname,
|
||||
SMB_STRUCT_STAT *psbuf)
|
||||
{
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
files_struct *fsp = NULL;
|
||||
int info = 0;
|
||||
|
||||
if (!VALID_STAT(*psbuf)) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (VALID_STAT_OF_DIR(*psbuf)) {
|
||||
status = open_directory(conn,
|
||||
fname,
|
||||
psbuf,
|
||||
DELETE_ACCESS,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_DELETE_ON_CLOSE,
|
||||
FILE_FLAG_POSIX_SEMANTICS|0777,
|
||||
&info,
|
||||
&fsp);
|
||||
} else {
|
||||
status = open_file_ntcreate(conn,
|
||||
fname,
|
||||
psbuf,
|
||||
DELETE_ACCESS,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
FILE_DELETE_ON_CLOSE,
|
||||
FILE_FLAG_POSIX_SEMANTICS|0777,
|
||||
INTERNAL_OPEN_ONLY,
|
||||
&info,
|
||||
&fsp);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
return close_file(fsp, NORMAL_CLOSE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
|
||||
****************************************************************************/
|
||||
@ -4861,6 +5108,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
pstring fname;
|
||||
files_struct *fsp = NULL;
|
||||
NTSTATUS status = NT_STATUS_OK;
|
||||
int data_return_size = 0;
|
||||
|
||||
if (!params) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
@ -5148,6 +5396,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
|
||||
case SMB_SET_POSIX_LOCK:
|
||||
{
|
||||
if (tran_call == TRANSACT2_SETFILEINFO) {
|
||||
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
|
||||
}
|
||||
status = smb_set_posix_lock(conn,
|
||||
inbuf,
|
||||
length,
|
||||
@ -5157,6 +5408,37 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
break;
|
||||
}
|
||||
|
||||
case SMB_POSIX_PATH_OPEN:
|
||||
{
|
||||
if (tran_call != TRANSACT2_SETPATHINFO) {
|
||||
/* We must have a pathname for this. */
|
||||
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
|
||||
}
|
||||
|
||||
status = smb_posix_open(conn,
|
||||
ppdata,
|
||||
total_data,
|
||||
fname,
|
||||
&sbuf,
|
||||
&data_return_size);
|
||||
break;
|
||||
}
|
||||
|
||||
case SMB_POSIX_PATH_UNLINK:
|
||||
{
|
||||
if (tran_call != TRANSACT2_SETPATHINFO) {
|
||||
/* We must have a pathname for this. */
|
||||
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
|
||||
}
|
||||
|
||||
status = smb_posix_unlink(conn,
|
||||
pdata,
|
||||
total_data,
|
||||
fname,
|
||||
&sbuf);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
|
||||
}
|
||||
@ -5178,7 +5460,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
}
|
||||
|
||||
SSVAL(params,0,0);
|
||||
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
|
||||
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user