1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-04 08:22:08 +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 used to be commit 83dbbdff34)
This commit is contained in:
Jeremy Allison
2007-02-06 21:05:34 +00:00
committed by Gerald (Jerry) Carter
parent c04068a42b
commit 7a5fa7f12e
15 changed files with 545 additions and 160 deletions

View File

@ -515,6 +515,7 @@ typedef struct files_struct {
BOOL aio_write_behind; BOOL aio_write_behind;
BOOL lockdb_clean; BOOL lockdb_clean;
BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */ BOOL initial_delete_on_close; /* Only set at NTCreateX if file was created. */
BOOL posix_open;
char *fsp_name; char *fsp_name;
struct vfs_fsp_data *vfs_extension; struct vfs_fsp_data *vfs_extension;
@ -736,6 +737,8 @@ struct pending_message_list {
DATA_BLOB private_data; DATA_BLOB private_data;
}; };
#define SHARE_MODE_FLAG_POSIX_OPEN 0x1
/* struct returned by get_share_modes */ /* struct returned by get_share_modes */
struct share_mode_entry { struct share_mode_entry {
struct process_id pid; struct process_id pid;
@ -752,6 +755,7 @@ struct share_mode_entry {
SMB_INO_T inode; SMB_INO_T inode;
unsigned long share_file_id; unsigned long share_file_id;
uint32 uid; /* uid of file opener. */ uint32 uid; /* uid of file opener. */
uint16 flags; /* POSIX_OPEN only defined so far... */
}; };
/* oplock break message definition - linearization of share_mode_entry. /* oplock break message definition - linearization of share_mode_entry.
@ -769,10 +773,11 @@ Offset Data length.
36 SMB_INO_T inode 8 bytes 36 SMB_INO_T inode 8 bytes
44 unsigned long file_id 4 bytes 44 unsigned long file_id 4 bytes
48 uint32 uid 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 { struct share_mode_lock {
const char *servicepath; /* canonicalized. */ const char *servicepath; /* canonicalized. */
@ -1580,19 +1585,19 @@ extern int chain_size;
* Note these must fit into 16-bits. * Note these must fit into 16-bits.
*/ */
#define NO_OPLOCK 0 #define NO_OPLOCK 0x0
#define EXCLUSIVE_OPLOCK 1 #define EXCLUSIVE_OPLOCK 0x1
#define BATCH_OPLOCK 2 #define BATCH_OPLOCK 0x2
#define LEVEL_II_OPLOCK 4 #define LEVEL_II_OPLOCK 0x4
/* The following are Samba-private. */ /* The following are Samba-private. */
#define INTERNAL_OPEN_ONLY 8 #define INTERNAL_OPEN_ONLY 0x8
#define FAKE_LEVEL_II_OPLOCK 16 /* Client requested no_oplock, but we have to #define FAKE_LEVEL_II_OPLOCK 0x10 /* Client requested no_oplock, but we have to
* inform potential level2 holders on * inform potential level2 holders on
* write. */ * write. */
#define DEFERRED_OPEN_ENTRY 32 #define DEFERRED_OPEN_ENTRY 0x20
#define UNUSED_SHARE_MODE_ENTRY 64 #define UNUSED_SHARE_MODE_ENTRY 0x40
#define FORCE_OPLOCK_BREAK_TO_NONE 128 #define FORCE_OPLOCK_BREAK_TO_NONE 0x80
/* None of the following should ever appear in fsp->oplock_request. */ /* 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) #define SAMBA_PRIVATE_OPLOCK_MASK (INTERNAL_OPEN_ONLY|DEFERRED_OPEN_ENTRY|UNUSED_SHARE_MODE_ENTRY|FORCE_OPLOCK_BREAK_TO_NONE)

View File

@ -446,6 +446,13 @@ Offset Size Name
/* Only valid for setfileinfo */ /* Only valid for setfileinfo */
#define SMB_SET_POSIX_LOCK 0x208 #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 */ /* Transact 2 Find First levels */
#define SMB_FIND_FILE_UNIX 0x202 #define SMB_FIND_FILE_UNIX 0x202
@ -477,6 +484,7 @@ Offset Size Name
#define CIFS_UNIX_EXTATTR_CAP 0x8 /* for support of chattr #define CIFS_UNIX_EXTATTR_CAP 0x8 /* for support of chattr
(chflags) and lsattr */ (chflags) and lsattr */
#define CIFS_UNIX_POSIX_PATHNAMES_CAP 0x10 /* Use POSIX pathnames on the wire. */ #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 #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 #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_type - 0 = Read, 1 = Write, 2 = Unlock
[2 bytes] lock_flags - 1 = Wait (only valid for setlock) [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_WRITE 1
#define POSIX_LOCK_TYPE_UNLOCK 2 #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 #endif

View File

@ -154,6 +154,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
out->dev = (SMB_DEV_T)in->dev; out->dev = (SMB_DEV_T)in->dev;
out->inode = (SMB_INO_T)in->ino; out->inode = (SMB_INO_T)in->ino;
out->uid = (uint32)geteuid(); out->uid = (uint32)geteuid();
out->flags = 0;
} }
/* /*

View File

@ -81,7 +81,7 @@ BOOL is_locked(files_struct *fsp,
enum brl_type lock_type) enum brl_type lock_type)
{ {
int strict_locking = lp_strict_locking(fsp->conn->params); 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; BOOL ret = True;
if (count == 0) { 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 " slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: %s "
"pid = %s, share_access = 0x%x, private_options = 0x%x, " "pid = %s, share_access = 0x%x, private_options = 0x%x, "
"access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " "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, num,
e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "", e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
procid_str_static(&e->pid), procid_str_static(&e->pid),
e->share_access, e->private_options, e->share_access, e->private_options,
e->access_mask, e->op_mid, e->op_type, e->share_file_id, 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; return share_str;
} }
@ -912,6 +913,7 @@ static void fill_share_mode_entry(struct share_mode_entry *e,
e->inode = fsp->inode; e->inode = fsp->inode;
e->share_file_id = fsp->fh->file_id; e->share_file_id = fsp->fh->file_id;
e->uid = (uint32)uid; 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, 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->dev = dev;
e->inode = ino; e->inode = ino;
e->uid = (uint32)-1; e->uid = (uint32)-1;
e->flags = 0;
} }
static void add_share_mode_entry(struct share_mode_lock *lck, static void add_share_mode_entry(struct share_mode_lock *lck,

View File

@ -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. 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 saved_errno = 0;
int ret; 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); ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
fsp->fh->fd = -1; fsp->fh->fd = -1;
return ret; return map_nt_error_from_unix(errno);
} }
if (get_windows_lock_ref_count(fsp)) { 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); add_fd_to_close_entry(fsp);
fsp->fh->fd = -1; 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); ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
if (saved_errno != 0) { if (ret == 0 && saved_errno != 0) {
errno = saved_errno; errno = saved_errno;
ret = -1; ret = -1;
} }
fsp->fh->fd = -1; fsp->fh->fd = -1;
return ret; if (ret == -1) {
return map_nt_error_from_unix(errno);
}
return NT_STATUS_OK;
} }
/**************************************************************************** /****************************************************************************

View File

@ -5589,17 +5589,23 @@ void lp_set_posix_pathnames(void)
Global state for POSIX lock processing - CIFS unix extensions. 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 */ 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; posix_cifsx_locktype = val;
} }

View File

@ -2081,6 +2081,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecur
FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, FILE_OPEN,
0, 0,
FILE_ATTRIBUTE_DIRECTORY,
NULL, &fsp); NULL, &fsp);
if (!NT_STATUS_IS_OK(nt_status)) { 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_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, FILE_OPEN,
0, 0,
FILE_ATTRIBUTE_DIRECTORY,
NULL, &fsp); NULL, &fsp);
if (!NT_STATUS_IS_OK(nt_status)) { if (!NT_STATUS_IS_OK(nt_status)) {

View File

@ -2,7 +2,7 @@
Unix SMB/CIFS implementation. Unix SMB/CIFS implementation.
file closing file closing
Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 1992-2004. Copyright (C) Jeremy Allison 1992-2007.
Copyright (C) Volker Lendecke 2005 Copyright (C) Volker Lendecke 2005
This program is free software; you can redistribute it and/or modify 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. 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; connection_struct *conn = fsp->conn;
int ret = 0;
if (fsp->fh->fd != -1) { if (fsp->fh->fd != -1) {
if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) if(flush_write_cache(fsp, CLOSE_FLUSH) == -1) {
ret = -1; status = map_nt_error_from_unix(errno);
}
delete_write_cache(fsp); delete_write_cache(fsp);
} }
conn->num_files_open--; conn->num_files_open--;
SAFE_FREE(fsp->wbmpx_ptr); SAFE_FREE(fsp->wbmpx_ptr);
return status;
return ret;
} }
/**************************************************************************** /****************************************************************************
@ -195,9 +194,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
if (delete_file) { if (delete_file) {
int i; int i;
/* See if others still have the file open. If this is the /* 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++) { 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; delete_file = False;
break; break;
} }
@ -282,12 +285,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
fsp->fsp_name, strerror(errno) )); fsp->fsp_name, strerror(errno) ));
status = map_nt_error_from_unix(errno); status = map_nt_error_from_unix(errno);
goto done;
} }
status = NT_STATUS_FILE_DELETED;
done: done:
/* unbecome user. */ /* unbecome user. */
pop_sec_ctx(); 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. 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; connection_struct *conn = fsp->conn;
int saved_errno = 0;
int err = 0;
int err1 = 0;
if (fsp->aio_write_behind) { 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); int ret = wait_for_aio_completion(fsp);
if (ret) { if (ret) {
saved_errno = ret; saved_status1 = map_nt_error_from_unix(ret);
err1 = -1;
} }
} else { } else {
cancel_aio_by_fsp(fsp); 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. * error here, we must remember this.
*/ */
if (close_filestruct(fsp) == -1) { saved_status2 = close_filestruct(fsp);
saved_errno = errno;
err1 = -1;
}
if (fsp->print_file) { if (fsp->print_file) {
print_fsp_end(fsp, close_type); print_fsp_end(fsp, close_type);
file_free(fsp); file_free(fsp);
return 0; return NT_STATUS_OK;
} }
/* If this is an old DOS or FCB open and we have multiple opens on /* 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) { if (fsp->fh->ref_count == 1) {
/* Should we return on error here... ? */ /* 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) { 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); locking_close_file(fsp);
err = fd_close(conn, fsp); status = 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;
}
/* check for magic scripts */ /* check for magic scripts */
if (close_type == NORMAL_CLOSE) { 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); 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", DEBUG(2,("%s closed file %s (numopen=%d) %s\n",
conn->user,fsp->fsp_name, conn->user,fsp->fsp_name,
conn->num_files_open, conn->num_files_open,
(err == -1 || err1 == -1) ? strerror(saved_errno) : "")); nt_errstr(status) ));
file_free(fsp); file_free(fsp);
return status;
if (err == -1 || err1 == -1) {
errno = saved_errno;
return saved_errno;
} else {
return 0;
}
} }
/**************************************************************************** /****************************************************************************
Close a directory opened by an NT SMB call. 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; struct share_mode_lock *lck = 0;
BOOL delete_dir = False; BOOL delete_dir = False;
NTSTATUS status = NT_STATUS_OK;
/* /*
* NT can set delete_on_close of the last open * 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) { if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name)); 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)) { 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) { if (delete_dir) {
int i; int i;
/* See if others still have the dir open. If this is the /* 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++) { 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; delete_dir = False;
break; break;
} }
@ -469,7 +470,7 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
TALLOC_FREE(lck); 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", DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
fsp->fsp_name, ok ? "succeeded" : "failed" )); 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. * 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); remove_pending_change_notify_requests_by_fid(fsp, NT_STATUS_DELETE_PENDING);
} }
} else { } else {
@ -496,35 +497,35 @@ static int close_directory(files_struct *fsp, enum file_close_type close_type)
*/ */
close_filestruct(fsp); close_filestruct(fsp);
file_free(fsp); file_free(fsp);
return 0; return status;
} }
/**************************************************************************** /****************************************************************************
Close a 'stat file' opened internally. 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. * Do the code common to files and directories.
*/ */
close_filestruct(fsp); close_filestruct(fsp);
file_free(fsp); file_free(fsp);
return 0; return NT_STATUS_OK;
} }
/**************************************************************************** /****************************************************************************
Close a files_struct. 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); return close_directory(fsp, close_type);
else if (fsp->is_stat) } else if (fsp->is_stat) {
return close_stat(fsp); return close_stat(fsp);
else if (fsp->fake_file_handle != NULL) } else if (fsp->fake_file_handle != NULL) {
return close_fake_file(fsp); return close_fake_file(fsp);
else }
return close_normal_file(fsp, close_type); return close_normal_file(fsp, close_type);
} }

View File

@ -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_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN, FILE_OPEN,
0, /* no create options. */ 0, /* no create options. */
FILE_ATTRIBUTE_DIRECTORY,
NULL, &fsp); NULL, &fsp);
} else { } else {
status = open_file_stat(conn, name, pst, &fsp); status = open_file_stat(conn, name, pst, &fsp);

View File

@ -160,8 +160,8 @@ void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh)
(*fh) = NULL; (*fh) = NULL;
} }
int close_fake_file(files_struct *fsp) NTSTATUS close_fake_file(files_struct *fsp)
{ {
file_free(fsp); file_free(fsp);
return 0; return NT_STATUS_OK;
} }

View File

@ -281,10 +281,10 @@ static BOOL saved_short_case_preserve;
Save case semantics. 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)) { if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
return; return file_attributes;
} }
saved_case_sensitive = conn->case_sensitive; 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_sensitive = True;
conn->case_preserve = True; conn->case_preserve = True;
conn->short_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 flags = IVAL(inbuf,smb_ntcreate_Flags);
uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
uint32 new_file_attributes;
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); 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. * 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); status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -679,6 +682,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
share_access, share_access,
create_disposition, create_disposition,
create_options, create_options,
new_file_attributes,
&info, &fsp); &info, &fsp);
restore_case_semantics(conn, file_attributes); restore_case_semantics(conn, file_attributes);
@ -714,7 +718,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
share_access, share_access,
create_disposition, create_disposition,
create_options, create_options,
file_attributes, new_file_attributes,
oplock_request, oplock_request,
&info, &fsp); &info, &fsp);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
@ -756,6 +760,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
share_access, share_access,
create_disposition, create_disposition,
create_options, create_options,
new_file_attributes,
&info, &fsp); &info, &fsp);
if(!NT_STATUS_IS_OK(status)) { 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 flags;
uint32 access_mask; uint32 access_mask;
uint32 file_attributes; uint32 file_attributes;
uint32 new_file_attributes;
uint32 share_access; uint32 share_access;
uint32 create_disposition; uint32 create_disposition;
uint32 create_options; 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. * 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); 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, share_access,
create_disposition, create_disposition,
create_options, create_options,
new_file_attributes,
&info, &fsp); &info, &fsp);
if(!NT_STATUS_IS_OK(status)) { if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes); 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, share_access,
create_disposition, create_disposition,
create_options, create_options,
file_attributes, new_file_attributes,
oplock_request, oplock_request,
&info, &fsp); &info, &fsp);
@ -1364,6 +1371,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
share_access, share_access,
create_disposition, create_disposition,
create_options, create_options,
new_file_attributes,
&info, &fsp); &info, &fsp);
if(!NT_STATUS_IS_OK(status)) { if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes); restore_case_semantics(conn, file_attributes);
@ -1570,7 +1578,6 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
uint32 fattr; uint32 fattr;
int info; int info;
SMB_OFF_T ret=-1; SMB_OFF_T ret=-1;
int close_ret;
NTSTATUS status = NT_STATUS_OK; NTSTATUS status = NT_STATUS_OK;
ZERO_STRUCT(sbuf1); 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. */ /* Ensure the modtime is set correctly on the destination file. */
fsp_set_pending_modtime(fsp2, sbuf1.st_mtime); 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 /* 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 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; return NT_STATUS_DISK_FULL;
} }
if (close_ret != 0) { if (!NT_STATUS_IS_OK(status)) {
status = map_nt_error_from_unix(close_ret);
DEBUG(3,("copy_internals: Error %s copy file %s to %s\n", DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
nt_errstr(status), oldname, newname)); nt_errstr(status), oldname, newname));
} }

View File

@ -67,14 +67,13 @@ static BOOL fd_open(struct connection_struct *conn,
Close the file associated with a fsp. Close the file associated with a fsp.
****************************************************************************/ ****************************************************************************/
int fd_close(struct connection_struct *conn, NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp)
files_struct *fsp)
{ {
if (fsp->fh->fd == -1) { 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) { 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); return fd_close_posix(conn, fsp);
} }
@ -1118,6 +1117,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
int flags2=0; int flags2=0;
BOOL file_existed = VALID_STAT(*psbuf); BOOL file_existed = VALID_STAT(*psbuf);
BOOL def_acl = False; BOOL def_acl = False;
BOOL posix_open = False;
SMB_DEV_T dev = 0; SMB_DEV_T dev = 0;
SMB_INO_T inode = 0; SMB_INO_T inode = 0;
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED; NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
@ -1156,10 +1156,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return NT_STATUS_NO_MEMORY; return NT_STATUS_NO_MEMORY;
} }
/* We add aARCH to this as this mode is only used if the file is if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) {
* created new. */ posix_open = True;
unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname, unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
parent_dir); 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 " DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
"access_mask=0x%x share_access=0x%x " "access_mask=0x%x share_access=0x%x "
@ -1197,9 +1203,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return status; return status;
} }
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK; if (!posix_open) {
if (file_existed) { new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
existing_dos_attributes = dos_mode(conn, fname, psbuf); if (file_existed) {
existing_dos_attributes = dos_mode(conn, fname, psbuf);
}
} }
/* ignore any oplock requests if oplocks are disabled */ /* 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 /* We only care about matching attributes on file exists and
* overwrite. */ * overwrite. */
if (file_existed && ((create_disposition == FILE_OVERWRITE) || if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) ||
(create_disposition == FILE_OVERWRITE_IF))) { (create_disposition == FILE_OVERWRITE_IF))) {
if (!open_match_attributes(conn, fname, if (!open_match_attributes(conn, fname,
existing_dos_attributes, existing_dos_attributes,
@ -1359,7 +1367,11 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
} }
#endif /* O_SYNC */ #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 * We should really return a permission denied error if either
* O_CREAT or O_TRUNC are set, but for compatibility with * 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 fsp->access_mask = open_access_mask; /* We change this to the
* requested access_mask after * requested access_mask after
* the open is done. */ * the open is done. */
fsp->posix_open = posix_open;
/* Ensure no SAMBA_PRIVATE bits can be set. */ /* Ensure no SAMBA_PRIVATE bits can be set. */
fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK); 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 */ /* Files should be initially set as archive */
if (lp_map_archive(SNUM(conn)) || if (lp_map_archive(SNUM(conn)) ||
lp_store_dos_attributes(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, new_dos_attributes | aARCH, NULL,
parent_dir); parent_dir);
}
} }
} }
@ -1780,7 +1796,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* selected. * selected.
*/ */
if (!file_existed && !def_acl) { if (!posix_open && !file_existed && !def_acl) {
int saved_errno = errno; /* We might get ENOSYS in the next int saved_errno = errno; /* We might get ENOSYS in the next
* call.. */ * 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. 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); file_free(fsp);
return ret; return status;
} }
static NTSTATUS mkdir_internal(connection_struct *conn, const char *name, static NTSTATUS mkdir_internal(connection_struct *conn,
SMB_STRUCT_STAT *psbuf) const char *name,
uint32 file_attributes,
SMB_STRUCT_STAT *psbuf)
{ {
int ret= -1; int ret= -1;
mode_t mode; mode_t mode;
@ -1905,7 +1923,11 @@ static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
return NT_STATUS_NO_MEMORY; 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) { if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
return map_nt_error_from_unix(errno); 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); inherit_access_acl(conn, parent_dir, name, mode);
} }
/* if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
* Check if high bits should have been set, /*
* then (if bits are missing): add them. * Check if high bits should have been set,
* Consider bits automagically set by UNIX, i.e. SGID bit from parent * then (if bits are missing): add them.
* dir. * 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, if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
psbuf->st_mode | (mode & ~psbuf->st_mode)); SMB_VFS_CHMOD(conn, name,
psbuf->st_mode | (mode & ~psbuf->st_mode));
}
} }
/* Change the owner if required. */ /* Change the owner if required. */
@ -1963,6 +1987,7 @@ NTSTATUS open_directory(connection_struct *conn,
uint32 share_access, uint32 share_access,
uint32 create_disposition, uint32 create_disposition,
uint32 create_options, uint32 create_options,
uint32 file_attributes,
int *pinfo, int *pinfo,
files_struct **result) files_struct **result)
{ {
@ -1974,12 +1999,13 @@ NTSTATUS open_directory(connection_struct *conn,
DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, " DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
"share_access = 0x%x create_options = 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, fname,
(unsigned int)access_mask, (unsigned int)access_mask,
(unsigned int)share_access, (unsigned int)share_access,
(unsigned int)create_options, (unsigned int)create_options,
(unsigned int)create_disposition)); (unsigned int)create_disposition,
(unsigned int)file_attributes));
if (is_ntfs_stream_name(fname)) { if (is_ntfs_stream_name(fname)) {
DEBUG(0,("open_directory: %s is a stream name!\n", 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 /* If directory exists error. If directory doesn't
* exist create. */ * exist create. */
status = mkdir_internal(conn, fname, psbuf); status = mkdir_internal(conn,
fname,
file_attributes,
psbuf);
if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(status)) {
DEBUG(2, ("open_directory: unable to create " DEBUG(2, ("open_directory: unable to create "
"%s. Error was %s\n", fname, "%s. Error was %s\n", fname,
@ -2023,7 +2053,10 @@ NTSTATUS open_directory(connection_struct *conn,
* exist create. * exist create.
*/ */
status = mkdir_internal(conn, fname, psbuf); status = mkdir_internal(conn,
fname,
file_attributes,
psbuf);
if (NT_STATUS_IS_OK(status)) { if (NT_STATUS_IS_OK(status)) {
info = FILE_WAS_CREATED; info = FILE_WAS_CREATED;
@ -2081,6 +2114,8 @@ NTSTATUS open_directory(connection_struct *conn,
fsp->sent_oplock_break = NO_BREAK_SENT; fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = True; fsp->is_directory = True;
fsp->is_stat = False; fsp->is_stat = False;
fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
string_set(&fsp->fsp_name,fname); string_set(&fsp->fsp_name,fname);
lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, 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, status = open_directory(conn, directory, &sbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */ FILE_READ_ATTRIBUTES, /* Just a stat open */
FILE_SHARE_NONE, /* Ignored for stat opens */ 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)) { if (NT_STATUS_IS_OK(status)) {
close_file(fsp, NORMAL_CLOSE); close_file(fsp, NORMAL_CLOSE);

View File

@ -832,6 +832,7 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
SINO_T_VAL(msg,36,e->inode); SINO_T_VAL(msg,36,e->inode);
SIVAL(msg,44,e->share_file_id); SIVAL(msg,44,e->share_file_id);
SIVAL(msg,48,e->uid); 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->inode = INO_T_VAL(msg,36);
e->share_file_id = (unsigned long)IVAL(msg,44); e->share_file_id = (unsigned long)IVAL(msg,44);
e->uid = (uint32)IVAL(msg,48); e->uid = (uint32)IVAL(msg,48);
e->flags = (uint16)SVAL(msg,52);
} }
/**************************************************************************** /****************************************************************************

View File

@ -3108,9 +3108,9 @@ int reply_exit(connection_struct *conn,
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize) int dum_buffsize)
{ {
NTSTATUS status = NT_STATUS_OK;
int outsize = 0; int outsize = 0;
time_t mtime; time_t mtime;
int32 eclass = 0, err = 0;
files_struct *fsp = NULL; files_struct *fsp = NULL;
START_PROFILE(SMBclose); 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. * Special case - close NT SMB directory handle.
*/ */
DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
close_file(fsp,NORMAL_CLOSE); status = close_file(fsp,NORMAL_CLOSE);
} else { } else {
/* /*
* Close ordinary file. * Close ordinary file.
*/ */
int close_err;
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n", DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
fsp->fh->fd, fsp->fnum, 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. * a disk full error. If not then it was probably an I/O error.
*/ */
if((close_err = close_file(fsp,NORMAL_CLOSE)) != 0) { status = close_file(fsp,NORMAL_CLOSE);
errno = close_err;
END_PROFILE(SMBclose);
return (UNIXERROR(ERRHRD,ERRgeneral));
}
} }
/* We have a cached error */ if(!NT_STATUS_IS_OK(status)) {
if(eclass || err) {
END_PROFILE(SMBclose); END_PROFILE(SMBclose);
return ERROR_DOS(eclass,err); return ERROR_NT(status);
} }
END_PROFILE(SMBclose); END_PROFILE(SMBclose);
@ -3189,7 +3183,7 @@ int reply_writeclose(connection_struct *conn,
size_t numtowrite; size_t numtowrite;
ssize_t nwritten = -1; ssize_t nwritten = -1;
int outsize = 0; int outsize = 0;
int close_err = 0; NTSTATUS close_status = NT_STATUS_OK;
SMB_OFF_T startpos; SMB_OFF_T startpos;
char *data; char *data;
time_t mtime; time_t mtime;
@ -3223,7 +3217,7 @@ int reply_writeclose(connection_struct *conn,
if (numtowrite) { if (numtowrite) {
DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n", DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
fsp->fsp_name )); 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", 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)); return(UNIXERROR(ERRHRD,ERRdiskfull));
} }
if(close_err != 0) { if(!NT_STATUS_IS_OK(close_status)) {
errno = close_err;
END_PROFILE(SMBwriteclose); END_PROFILE(SMBwriteclose);
return(UNIXERROR(ERRHRD,ERRgeneral)); return ERROR_NT(close_status);
} }
outsize = set_message(outbuf,1,0,True); 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); int outsize = set_message(outbuf,0,0,False);
files_struct *fsp = file_fsp(inbuf,smb_vwv0); files_struct *fsp = file_fsp(inbuf,smb_vwv0);
int close_err = 0; NTSTATUS status;
START_PROFILE(SMBsplclose); START_PROFILE(SMBsplclose);
CHECK_FSP(fsp,conn); CHECK_FSP(fsp,conn);
@ -3468,12 +3461,11 @@ int reply_printclose(connection_struct *conn,
DEBUG(3,("printclose fd=%d fnum=%d\n", DEBUG(3,("printclose fd=%d fnum=%d\n",
fsp->fh->fd,fsp->fnum)); fsp->fh->fd,fsp->fnum));
close_err = close_file(fsp,NORMAL_CLOSE); status = close_file(fsp,NORMAL_CLOSE);
if(close_err != 0) { if(!NT_STATUS_IS_OK(status)) {
errno = close_err;
END_PROFILE(SMBsplclose); END_PROFILE(SMBsplclose);
return(UNIXERROR(ERRHRD,ERRgeneral)); return ERROR_NT(status);
} }
END_PROFILE(SMBsplclose); END_PROFILE(SMBsplclose);
@ -3707,7 +3699,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
The internals of the rmdir code - called elsewhere. 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; int ret;
SMB_STRUCT_STAT st; SMB_STRUCT_STAT st;
@ -3717,7 +3709,7 @@ BOOL rmdir_internals(connection_struct *conn, const char *directory)
notify_fname(conn, NOTIFY_ACTION_REMOVED, notify_fname(conn, NOTIFY_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_DIR_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
directory); directory);
return True; return NT_STATUS_OK;
} }
if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { 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) { if (ret != 0) {
DEBUG(3,("rmdir_internals: couldn't remove directory %s : " DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
"%s\n", directory,strerror(errno))); "%s\n", directory,strerror(errno)));
return False; return map_nt_error_from_unix(errno);
} }
notify_fname(conn, NOTIFY_ACTION_REMOVED, notify_fname(conn, NOTIFY_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_DIR_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
directory); 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)); 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); END_PROFILE(SMBrmdir);
return UNIXERROR(ERRDOS, ERRbadpath); return ERROR_NT(status);
} }
outsize = set_message(outbuf,0,0,False); 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 dosattrs;
uint32 new_create_disposition; uint32 new_create_disposition;
NTSTATUS status; NTSTATUS status;
int close_err;
pstrcpy(dest,dest1); pstrcpy(dest,dest1);
if (target_is_directory) { 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 * Thus we don't look at the error return from the
* close of fsp1. * close of fsp1.
*/ */
close_err = close_file(fsp2,NORMAL_CLOSE); status = close_file(fsp2,NORMAL_CLOSE);
if (close_err != 0) { if (!NT_STATUS_IS_OK(status)) {
return map_nt_error_from_unix(close_err); return status;
} }
if (ret != (SMB_OFF_T)src_sbuf.st_size) { if (ret != (SMB_OFF_T)src_sbuf.st_size) {

View File

@ -2529,7 +2529,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SBIG_UINT(pdata,4,((SMB_BIG_UINT)( SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
CIFS_UNIX_POSIX_ACLS_CAP| CIFS_UNIX_POSIX_ACLS_CAP|
CIFS_UNIX_POSIX_PATHNAMES_CAP| CIFS_UNIX_POSIX_PATHNAMES_CAP|
CIFS_UNIX_FCNTL_LOCKS_CAP))); CIFS_UNIX_FCNTL_LOCKS_CAP|
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
break; break;
case SMB_QUERY_POSIX_FS_INFO: case SMB_QUERY_POSIX_FS_INFO:
@ -2646,8 +2647,14 @@ cap_low = 0x%x, cap_high = 0x%x\n",
mangle_change_to_posix(); mangle_change_to_posix();
} }
if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) { if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
lp_set_posix_cifsx_locktype(POSIX_LOCK); !(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; break;
} }
@ -4845,6 +4852,246 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
tvs); 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). 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; pstring fname;
files_struct *fsp = NULL; files_struct *fsp = NULL;
NTSTATUS status = NT_STATUS_OK; NTSTATUS status = NT_STATUS_OK;
int data_return_size = 0;
if (!params) { if (!params) {
return ERROR_NT(NT_STATUS_INVALID_PARAMETER); 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: case SMB_SET_POSIX_LOCK:
{ {
if (tran_call == TRANSACT2_SETFILEINFO) {
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
status = smb_set_posix_lock(conn, status = smb_set_posix_lock(conn,
inbuf, inbuf,
length, length,
@ -5157,6 +5408,37 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
break; 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: default:
return ERROR_NT(NT_STATUS_INVALID_LEVEL); 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); 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; return -1;
} }