1
0
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:
Jeremy Allison 2007-02-06 21:05:34 +00:00 committed by Gerald (Jerry) Carter
parent b10f4cdfc0
commit 83dbbdff34
15 changed files with 545 additions and 160 deletions

View File

@ -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)

View File

@ -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

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->inode = (SMB_INO_T)in->ino;
out->uid = (uint32)geteuid();
out->flags = 0;
}
/*

View File

@ -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,

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.
****************************************************************************/
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;
}
/****************************************************************************

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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);
}

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_OPEN,
0, /* no create options. */
FILE_ATTRIBUTE_DIRECTORY,
NULL, &fsp);
} else {
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;
}
int close_fake_file(files_struct *fsp)
NTSTATUS close_fake_file(files_struct *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.
****************************************************************************/
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));
}

View File

@ -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);

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);
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);
}
/****************************************************************************

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 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) {

View File

@ -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;
}