summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-12-30 03:03:33 +0000
committerJeremy Allison <jra@samba.org>2006-12-30 03:03:33 +0000
commit5b8b7e86d207fac85bba2cc980532ff336dedc01 (patch)
tree680666af17eb08d0ba4a2a9afc7b28d8da703b8f
parent23d86c7a8e004f5908dc70eccfb8e6e342b760ab (diff)
downloadsamba-5b8b7e86d207fac85bba2cc980532ff336dedc01.tar.gz
samba-5b8b7e86d207fac85bba2cc980532ff336dedc01.tar.xz
samba-5b8b7e86d207fac85bba2cc980532ff336dedc01.zip
r20413: Merge Volker's open directory changes to 3.0.24.
I think they're correct, modulo more testing of error codes. Jeremy.
-rw-r--r--source/lib/util.c31
-rw-r--r--source/printing/nt_printing.c2
-rw-r--r--source/smbd/dosmode.c27
-rw-r--r--source/smbd/nttrans.c86
-rw-r--r--source/smbd/open.c390
-rw-r--r--source/smbd/posix_acls.c19
-rw-r--r--source/smbd/reply.c67
-rw-r--r--source/smbd/trans2.c37
-rw-r--r--source/smbd/vfs.c25
9 files changed, 387 insertions, 297 deletions
diff --git a/source/lib/util.c b/source/lib/util.c
index 9ac0b376123..5e2588e5b90 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -2620,6 +2620,37 @@ char *parent_dirname(const char *path)
return dirpath;
}
+BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
+ char **parent, const char **name)
+{
+ char *p;
+ ptrdiff_t len;
+
+ p = strrchr_m(dir, '/'); /* Find final '/', if any */
+
+ if (p == NULL) {
+ if (!(*parent = talloc_strdup(mem_ctx, "."))) {
+ return False;
+ }
+ if (name) {
+ *name = "";
+ }
+ return True;
+ }
+
+ len = p-dir;
+
+ if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
+ return False;
+ }
+ memcpy(*parent, dir, len);
+ (*parent)[len] = '\0';
+
+ if (name) {
+ *name = p+1;
+ }
+ return True;
+}
/*******************************************************************
Determine if a pattern contains any Microsoft wildcard characters.
diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c
index b74763b2e5e..541a60fef14 100644
--- a/source/printing/nt_printing.c
+++ b/source/printing/nt_printing.c
@@ -1800,7 +1800,7 @@ WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
DEBUG(5,("Creating first directory\n"));
slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
driver_unix_convert(new_dir, conn, NULL, &bad_path, &st);
- mkdir_internal(conn, new_dir, bad_path);
+ create_directory(conn, new_dir);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c
index 260a8dadbd6..1172fe3e6b5 100644
--- a/source/smbd/dosmode.c
+++ b/source/smbd/dosmode.c
@@ -59,7 +59,7 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path)
/****************************************************************************
Change a dos mode to a unix mode.
Base permission for files:
- if creating file and inheriting
+ if creating file and inheriting (i.e. parent_dir != NULL)
apply read/write bits from parent directory.
else
everybody gets read bit set
@@ -79,23 +79,26 @@ static uint32 set_offline_flag(connection_struct *conn, const char *const path)
}
****************************************************************************/
-mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname, BOOL creating_file)
+mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname,
+ const char *inherit_from_dir)
{
mode_t result = (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH);
- mode_t dir_mode = 0; /* Mode of the parent directory if inheriting. */
+ mode_t dir_mode = 0; /* Mode of the inherit_from directory if
+ * inheriting. */
if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
}
- if (fname && creating_file && lp_inherit_perms(SNUM(conn))) {
- char *dname;
+ if (fname && (inherit_from_dir != NULL)
+ && lp_inherit_perms(SNUM(conn))) {
SMB_STRUCT_STAT sbuf;
- dname = parent_dirname(fname);
- DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname));
- if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) {
- DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno)));
+ DEBUG(2, ("unix_mode(%s) inheriting from %s\n", fname,
+ inherit_from_dir));
+ if (SMB_VFS_STAT(conn, inherit_from_dir, &sbuf) != 0) {
+ DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n", fname,
+ inherit_from_dir, strerror(errno)));
return(0); /* *** shouldn't happen! *** */
}
@@ -429,7 +432,9 @@ uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
chmod a file - but preserve some bits.
********************************************************************/
-int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st, BOOL creating_file)
+int file_set_dosmode(connection_struct *conn, const char *fname,
+ uint32 dosmode, SMB_STRUCT_STAT *st,
+ const char *parent_dir)
{
SMB_STRUCT_STAT st1;
int mask=0;
@@ -462,7 +467,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode,
return 0;
}
- unixmode = unix_mode(conn,dosmode,fname, creating_file);
+ unixmode = unix_mode(conn,dosmode,fname, parent_dir);
/* preserve the s bits */
mask |= (S_ISUID | S_ISGID);
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index a0dc89a31a5..b429451ea88 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -68,8 +68,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params,
- int paramsize, char *pdata, int datasize)
+int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error,
+ char *params, int paramsize, char *pdata, int datasize)
{
int data_to_send = datasize;
int params_to_send = paramsize;
@@ -477,9 +477,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
START_PROFILE(SMBntcreateX);
- DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x \
-file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
-create_options = 0x%x root_dir_fid = 0x%x\n",
+ DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
+ "file_attributes = 0x%x, share_access = 0x%x, "
+ "create_disposition = 0x%x create_options = 0x%x "
+ "root_dir_fid = 0x%x\n",
(unsigned int)flags,
(unsigned int)access_mask,
(unsigned int)file_attributes,
@@ -686,6 +687,10 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
restore_case_semantics(conn, file_attributes);
if(!NT_STATUS_IS_OK(status)) {
+ if (!use_nt_status() && NT_STATUS_EQUAL(
+ status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+ }
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
@@ -758,6 +763,10 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
if(!NT_STATUS_IS_OK(status)) {
restore_case_semantics(conn, file_attributes);
+ if (!use_nt_status() && NT_STATUS_EQUAL(
+ status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+ }
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
@@ -959,7 +968,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
return -1;
}
@@ -1283,19 +1292,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
if (ea_len) {
- ctx = talloc_init("NTTRANS_CREATE_EA");
- if (!ctx) {
- talloc_destroy(ctx);
- restore_case_semantics(conn, file_attributes);
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
pdata = data + sd_len;
/* We have already checked that ea_len <= data_count here. */
- ea_list = read_nttrans_ea_list(ctx, pdata, ea_len);
+ ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata,
+ ea_len);
if (!ea_list ) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1309,7 +1311,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1329,7 +1330,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
create_options,
&info, &fsp);
if(!NT_STATUS_IS_OK(status)) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
@@ -1370,12 +1370,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
create_options,
&info, &fsp);
if(!NT_STATUS_IS_OK(status)) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
} else {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
@@ -1416,7 +1414,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (ea_len && (info == FILE_WAS_CREATED)) {
status = set_ea(conn, fsp, fname, ea_list);
- talloc_destroy(ctx);
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp,ERROR_CLOSE);
restore_case_semantics(conn, file_attributes);
@@ -1480,8 +1477,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
p = params;
if (extended_oplock_granted) {
- SCVAL(p,0, BATCH_OPLOCK_RETURN);
- } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
+ if (flags & REQUEST_BATCH_OPLOCK) {
+ SCVAL(p,0, BATCH_OPLOCK_RETURN);
+ } else {
+ SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN);
+ }
+ } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
} else {
SCVAL(p,0,NO_OPLOCK_RETURN);
@@ -1531,7 +1532,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
return -1;
}
@@ -1695,7 +1696,8 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
/* 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
case. JRA */
- file_set_dosmode(conn, newname, fattr, &sbuf2, True);
+ file_set_dosmode(conn, newname, fattr, &sbuf2,
+ parent_dirname(newname));
if (ret < (SMB_OFF_T)sbuf1.st_size) {
return NT_STATUS_DISK_FULL;
@@ -1883,7 +1885,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
/*
* Rename was successful.
*/
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
fsp->fsp_name, new_name));
@@ -1978,8 +1980,8 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
if(max_data_count < sd_size) {
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
- params, 4, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
+ params, 4, *ppdata, 0);
talloc_destroy(mem_ctx);
return -1;
}
@@ -2027,7 +2029,8 @@ security descriptor.\n"));
talloc_destroy(mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data,
+ (int)sd_size);
return -1;
}
@@ -2073,7 +2076,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
done:
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
}
@@ -2119,7 +2122,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
so we can know if we need to pre-allocate or not */
DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ 0);
return -1;
case FSCTL_0x000900C0:
@@ -2128,7 +2132,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ 0);
return -1;
case FSCTL_GET_REPARSE_POINT:
@@ -2137,7 +2142,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
return -1;
case FSCTL_SET_REPARSE_POINT:
@@ -2146,7 +2152,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
return -1;
case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
@@ -2259,7 +2266,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
talloc_destroy(shadow_data->mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ pdata, data_count);
return -1;
}
@@ -2311,7 +2319,8 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
/* this works for now... */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ NULL, 0);
return -1;
}
default:
@@ -2577,7 +2586,8 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
break;
}
- send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len);
+ send_nt_replies(outbuf, bufsize, nt_status, params, param_len,
+ pdata, data_len);
return -1;
}
@@ -2694,7 +2704,8 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRSRV,ERRerror);
}
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len,
+ pdata, data_len);
return -1;
}
@@ -2865,6 +2876,7 @@ int reply_nttrans(connection_struct *conn,
state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
state->param = NULL;
state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);
+ state->max_param_return = IVAL(inbuf,smb_nt_MaxParameterCount);
/* setup count is in *words* */
state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount);
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 9d9b7a074c1..8d67afd6998 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -84,100 +84,111 @@ int fd_close(struct connection_struct *conn,
Do this by fd if possible.
****************************************************************************/
-static void change_owner_to_parent(connection_struct *conn,
- files_struct *fsp,
- const char *fname,
- SMB_STRUCT_STAT *psbuf)
+static void change_file_owner_to_parent(connection_struct *conn,
+ const char *inherit_from_dir,
+ files_struct *fsp)
{
- const char *parent_path = parent_dirname(fname);
SMB_STRUCT_STAT parent_st;
int ret;
- ret = SMB_VFS_STAT(conn, parent_path, &parent_st);
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
if (ret == -1) {
- DEBUG(0,("change_owner_to_parent: failed to stat parent "
+ DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
"directory %s. Error was %s\n",
- parent_path, strerror(errno) ));
+ inherit_from_dir, strerror(errno) ));
return;
}
- if (fsp && fsp->fh->fd != -1) {
- become_root();
- ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1);
- unbecome_root();
- if (ret == -1) {
- DEBUG(0,("change_owner_to_parent: failed to fchown "
- "file %s to parent directory uid %u. Error "
- "was %s\n", fname,
- (unsigned int)parent_st.st_uid,
- strerror(errno) ));
- }
+ become_root();
+ ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1);
+ unbecome_root();
+ if (ret == -1) {
+ DEBUG(0,("change_file_owner_to_parent: failed to fchown "
+ "file %s to parent directory uid %u. Error "
+ "was %s\n", fsp->fsp_name,
+ (unsigned int)parent_st.st_uid,
+ strerror(errno) ));
+ }
- DEBUG(10,("change_owner_to_parent: changed new file %s to "
- "parent directory uid %u.\n", fname,
- (unsigned int)parent_st.st_uid ));
+ DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
+ "parent directory uid %u.\n", fsp->fsp_name,
+ (unsigned int)parent_st.st_uid ));
+}
- } else {
- /* We've already done an lstat into psbuf, and we know it's a
- directory. If we can cd into the directory and the dev/ino
- are the same then we can safely chown without races as
- we're locking the directory in place by being in it. This
- should work on any UNIX (thanks tridge :-). JRA.
- */
-
- pstring saved_dir;
- SMB_STRUCT_STAT sbuf;
-
- if (!vfs_GetWd(conn,saved_dir)) {
- DEBUG(0,("change_owner_to_parent: failed to get "
- "current working directory\n"));
- return;
- }
+static void change_dir_owner_to_parent(connection_struct *conn,
+ const char *inherit_from_dir,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ pstring saved_dir;
+ SMB_STRUCT_STAT sbuf;
+ SMB_STRUCT_STAT parent_st;
+ int ret;
- /* Chdir into the new path. */
- if (vfs_ChDir(conn, fname) == -1) {
- DEBUG(0,("change_owner_to_parent: failed to change "
- "current working directory to %s. Error "
- "was %s\n", fname, strerror(errno) ));
- goto out;
- }
+ ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
+ if (ret == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
+ "directory %s. Error was %s\n",
+ inherit_from_dir, strerror(errno) ));
+ return;
+ }
- if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
- DEBUG(0,("change_owner_to_parent: failed to stat "
- "directory '.' (%s) Error was %s\n",
- fname, strerror(errno)));
- goto out;
- }
+ /* We've already done an lstat into psbuf, and we know it's a
+ directory. If we can cd into the directory and the dev/ino
+ are the same then we can safely chown without races as
+ we're locking the directory in place by being in it. This
+ should work on any UNIX (thanks tridge :-). JRA.
+ */
- /* Ensure we're pointing at the same place. */
- if (sbuf.st_dev != psbuf->st_dev ||
- sbuf.st_ino != psbuf->st_ino ||
- sbuf.st_mode != psbuf->st_mode ) {
- DEBUG(0,("change_owner_to_parent: "
- "device/inode/mode on directory %s changed. "
- "Refusing to chown !\n", fname ));
- goto out;
- }
+ if (!vfs_GetWd(conn,saved_dir)) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to get "
+ "current working directory\n"));
+ return;
+ }
- become_root();
- ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
- unbecome_root();
- if (ret == -1) {
- DEBUG(10,("change_owner_to_parent: failed to chown "
- "directory %s to parent directory uid %u. "
- "Error was %s\n", fname,
- (unsigned int)parent_st.st_uid, strerror(errno) ));
- goto out;
- }
+ /* Chdir into the new path. */
+ if (vfs_ChDir(conn, fname) == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to change "
+ "current working directory to %s. Error "
+ "was %s\n", fname, strerror(errno) ));
+ goto out;
+ }
- DEBUG(10,("change_owner_to_parent: changed ownership of new "
- "directory %s to parent directory uid %u.\n",
- fname, (unsigned int)parent_st.st_uid ));
+ if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
+ DEBUG(0,("change_dir_owner_to_parent: failed to stat "
+ "directory '.' (%s) Error was %s\n",
+ fname, strerror(errno)));
+ goto out;
+ }
- out:
+ /* Ensure we're pointing at the same place. */
+ if (sbuf.st_dev != psbuf->st_dev ||
+ sbuf.st_ino != psbuf->st_ino ||
+ sbuf.st_mode != psbuf->st_mode ) {
+ DEBUG(0,("change_dir_owner_to_parent: "
+ "device/inode/mode on directory %s changed. "
+ "Refusing to chown !\n", fname ));
+ goto out;
+ }
- vfs_ChDir(conn,saved_dir);
+ become_root();
+ ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
+ unbecome_root();
+ if (ret == -1) {
+ DEBUG(10,("change_dir_owner_to_parent: failed to chown "
+ "directory %s to parent directory uid %u. "
+ "Error was %s\n", fname,
+ (unsigned int)parent_st.st_uid, strerror(errno) ));
+ goto out;
}
+
+ DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
+ "directory %s to parent directory uid %u.\n",
+ fname, (unsigned int)parent_st.st_uid ));
+
+ out:
+
+ vfs_ChDir(conn,saved_dir);
}
/****************************************************************************
@@ -186,6 +197,7 @@ static void change_owner_to_parent(connection_struct *conn,
static NTSTATUS open_file(files_struct *fsp,
connection_struct *conn,
+ const char *parent_dir,
const char *fname,
SMB_STRUCT_STAT *psbuf,
int flags,
@@ -282,9 +294,19 @@ static NTSTATUS open_file(files_struct *fsp,
return map_nt_error_from_unix(errno);
}
- /* Inherit the ACL if the file was created. */
if ((local_flags & O_CREAT) && !file_existed) {
- inherit_access_acl(conn, fname, unx_mode);
+
+ /* Inherit the ACL if required */
+ if (lp_inherit_perms(SNUM(conn))) {
+ inherit_access_acl(conn, parent_dir, fname,
+ unx_mode);
+ }
+
+ /* Change the owner if required. */
+ if (lp_inherit_owner(SNUM(conn))) {
+ change_file_owner_to_parent(conn, parent_dir,
+ fsp);
+ }
}
} else {
@@ -1105,6 +1127,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
uint32 open_access_mask = access_mask;
NTSTATUS status;
int ret_flock;
+ char *parent_dir;
+ const char *newname;
if (conn->printer) {
/*
@@ -1121,9 +1145,15 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return print_fsp_open(conn, fname, result);
}
+ if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir,
+ &newname)) {
+ 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, True);
+ 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 "
@@ -1175,7 +1205,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
/* this is for OS/2 long file names - say we don't support them */
if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
/* OS/2 Workplace shell fix may be main code stream in a later
- * release. */
+ * release. */
DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
"supported.\n"));
if (use_nt_status()) {
@@ -1535,8 +1565,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
*/
if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
- (def_acl = directory_has_default_acl(conn,
- parent_dirname(fname)))) {
+ (def_acl = directory_has_default_acl(conn, parent_dir))) {
unx_mode = 0777;
}
@@ -1550,8 +1579,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* open_file strips any O_TRUNC flags itself.
*/
- fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
- access_mask, open_access_mask);
+ fsp_open = open_file(fsp, conn, parent_dir, fname, psbuf, flags|flags2,
+ unx_mode, access_mask, open_access_mask);
if (!NT_STATUS_IS_OK(fsp_open)) {
if (lck != NULL) {
@@ -1639,7 +1668,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access);
if(ret_flock == -1 ){
- talloc_free(lck);
+ TALLOC_FREE(lck);
fd_close(conn, fsp);
file_free(fsp);
@@ -1689,11 +1718,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
} else {
info = FILE_WAS_CREATED;
- /* Change the owner if required. */
- if (lp_inherit_owner(SNUM(conn))) {
- change_owner_to_parent(conn, fsp, fsp->fsp_name,
- psbuf);
- }
}
if (pinfo) {
@@ -1741,7 +1765,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
lp_store_dos_attributes(SNUM(conn))) {
file_set_dosmode(conn, fname,
new_dos_attributes | aARCH, NULL,
- True);
+ parent_dir);
}
}
@@ -1821,7 +1845,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
/* note! we must use a non-zero desired access or we don't get
a real file descriptor. Oh what a twisted web we weave. */
- status = open_file(fsp,conn,fname,psbuf,O_WRONLY,0,FILE_WRITE_DATA,FILE_WRITE_DATA);
+ status = open_file(fsp, conn, NULL, fname, psbuf, O_WRONLY, 0,
+ FILE_WRITE_DATA, FILE_WRITE_DATA);
/*
* This is not a user visible file open.
@@ -1849,6 +1874,73 @@ int close_file_fchmod(files_struct *fsp)
return ret;
}
+static NTSTATUS mkdir_internal(connection_struct *conn, const char *name,
+ SMB_STRUCT_STAT *psbuf)
+{
+ int ret= -1;
+ mode_t mode;
+ char *parent_dir;
+ const char *dirname;
+
+ if(!CAN_WRITE(conn)) {
+ DEBUG(5,("mkdir_internal: failing create on read-only share "
+ "%s\n", lp_servicename(SNUM(conn))));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!check_name(name, conn)) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir,
+ &dirname)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ mode = unix_mode(conn, aDIR, name, parent_dir);
+
+ if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ /* Ensure we're checking for a symlink here.... */
+ /* We don't want to get caught by a symlink racer. */
+
+ if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
+ DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
+ name, strerror(errno)));
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (!S_ISDIR(psbuf->st_mode)) {
+ DEBUG(0, ("Directory just '%s' created is not a directory\n",
+ name));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (lp_inherit_perms(SNUM(conn))) {
+ 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));
+ }
+
+ /* Change the owner if required. */
+ if (lp_inherit_owner(SNUM(conn))) {
+ change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
+ }
+
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
@@ -1865,7 +1957,6 @@ NTSTATUS open_directory(connection_struct *conn,
{
files_struct *fsp = NULL;
BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
- BOOL create_dir = False;
struct share_mode_lock *lck = NULL;
NTSTATUS status;
int info = 0;
@@ -1886,44 +1977,53 @@ NTSTATUS open_directory(connection_struct *conn,
switch( create_disposition ) {
case FILE_OPEN:
- /* If directory exists open. If directory doesn't
- * exist error. */
- if (!dir_existed) {
- DEBUG(5,("open_directory: FILE_OPEN requested "
- "for directory %s and it doesn't "
- "exist.\n", fname ));
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
+
info = FILE_WAS_OPENED;
+
+ /*
+ * We want to follow symlinks here.
+ */
+
+ if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
break;
case FILE_CREATE:
+
/* If directory exists error. If directory doesn't
* exist create. */
- if (dir_existed) {
- DEBUG(5,("open_directory: FILE_CREATE "
- "requested for directory %s and it "
- "already exists.\n", fname ));
- if (use_nt_status()) {
- return NT_STATUS_OBJECT_NAME_COLLISION;
- } else {
- return NT_STATUS_DOS(ERRDOS,
- ERRfilexists);
- }
+
+ status = mkdir_internal(conn, fname, psbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2, ("open_directory: unable to create "
+ "%s. Error was %s\n", fname,
+ nt_errstr(status)));
+ return status;
}
- create_dir = True;
+
info = FILE_WAS_CREATED;
break;
case FILE_OPEN_IF:
- /* If directory exists open. If directory doesn't
- * exist create. */
- if (!dir_existed) {
- create_dir = True;
+ /*
+ * If directory exists open. If directory doesn't
+ * exist create.
+ */
+
+ status = mkdir_internal(conn, fname, psbuf);
+
+ if (NT_STATUS_IS_OK(status)) {
info = FILE_WAS_CREATED;
- } else {
+ }
+
+ if (NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
info = FILE_WAS_OPENED;
+ status = NT_STATUS_OK;
}
+
break;
case FILE_SUPERSEDE:
@@ -1936,35 +2036,10 @@ NTSTATUS open_directory(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- if (create_dir) {
- /*
- * Try and create the directory.
- */
-
- /* We know bad_path is false as it's caught earlier. */
-
- status = mkdir_internal(conn, fname, False);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(2,("open_directory: unable to create %s. "
- "Error was %s\n", fname, strerror(errno) ));
- /* Ensure we return the correct NT status to the
- * client. */
- return status;
- }
-
- /* Ensure we're checking for a symlink here.... */
- /* We don't want to get caught by a symlink racer. */
-
- if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) {
- return map_nt_error_from_unix(errno);
- }
-
- if(!S_ISDIR(psbuf->st_mode)) {
- DEBUG(0,("open_directory: %s is not a directory !\n",
- fname ));
- return NT_STATUS_NOT_A_DIRECTORY;
- }
+ if(!S_ISDIR(psbuf->st_mode)) {
+ DEBUG(5,("open_directory: %s is not a directory !\n",
+ fname ));
+ return NT_STATUS_NOT_A_DIRECTORY;
}
status = file_new(conn, &fsp);
@@ -2036,11 +2111,6 @@ NTSTATUS open_directory(connection_struct *conn,
TALLOC_FREE(lck);
- /* Change the owner if required. */
- if ((info == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) {
- change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf);
- }
-
if (pinfo) {
*pinfo = info;
}
@@ -2051,6 +2121,26 @@ NTSTATUS open_directory(connection_struct *conn,
return NT_STATUS_OK;
}
+NTSTATUS create_directory(connection_struct *conn, const char *directory)
+{
+ NTSTATUS status;
+ SMB_STRUCT_STAT sbuf;
+ files_struct *fsp;
+
+ SET_STAT_INVALID(sbuf);
+
+ 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);
+
+ if (NT_STATUS_IS_OK(status)) {
+ close_file(fsp, NORMAL_CLOSE);
+ }
+
+ return status;
+}
+
/****************************************************************************
Open a pseudo-file (no locking checks - a 'stat' open).
****************************************************************************/
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 4cdb0908ce8..ceeff847214 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -1878,7 +1878,10 @@ static mode_t create_default_mode(files_struct *fsp, BOOL interitable_mode)
int snum = SNUM(fsp->conn);
mode_t and_bits = (mode_t)0;
mode_t or_bits = (mode_t)0;
- mode_t mode = interitable_mode ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name, False) : S_IRUSR;
+ mode_t mode = interitable_mode
+ ? unix_mode( fsp->conn, FILE_ATTRIBUTE_ARCHIVE, fsp->fsp_name,
+ NULL )
+ : S_IRUSR;
if (fsp->is_directory)
mode |= (S_IWUSR|S_IXUSR);
@@ -3457,19 +3460,17 @@ int chmod_acl(connection_struct *conn, const char *name, mode_t mode)
}
/****************************************************************************
- If "inherit permissions" is set and the parent directory has no default
- ACL but it does have an Access ACL, inherit this Access ACL to file name.
+ If the parent directory has no default ACL but it does have an Access ACL,
+ inherit this Access ACL to file name.
****************************************************************************/
-int inherit_access_acl(connection_struct *conn, const char *name, mode_t mode)
+int inherit_access_acl(connection_struct *conn, const char *inherit_from_dir,
+ const char *name, mode_t mode)
{
- pstring dirname;
- pstrcpy(dirname, parent_dirname(name));
-
- if (!lp_inherit_perms(SNUM(conn)) || directory_has_default_acl(conn, dirname))
+ if (directory_has_default_acl(conn, inherit_from_dir))
return 0;
- return copy_access_acl(conn, dirname, name, mode);
+ return copy_access_acl(conn, inherit_from_dir, name, mode);
}
/****************************************************************************
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index a9c6aa947fc..04caa4b2284 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -3745,47 +3745,6 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
}
/****************************************************************************
- The guts of the mkdir command, split out so it may be called by the NT SMB
- code.
-****************************************************************************/
-
-NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
-{
- int ret= -1;
-
- if(!CAN_WRITE(conn)) {
- DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
- errno = EACCES;
- return map_nt_error_from_unix(errno);
- }
-
- if (bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- }
-
- if (!check_name(directory, conn)) {
- if(errno == ENOENT) {
- if (bad_path) {
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- } else {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- }
- return map_nt_error_from_unix(errno);
- }
-
- ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
- if (ret == -1) {
- if(errno == ENOENT) {
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
- }
- return map_nt_error_from_unix(errno);
- }
-
- return NT_STATUS_OK;
-}
-
-/****************************************************************************
Reply to a mkdir.
****************************************************************************/
@@ -3796,7 +3755,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
BOOL bad_path = False;
SMB_STRUCT_STAT sbuf;
- files_struct *fsp;
START_PROFILE(SMBmkdir);
@@ -3810,17 +3768,15 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(directory,conn,0,&bad_path,&sbuf);
- 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);
+ status = create_directory(conn, directory);
- DEBUG(5, ("open_directory returned %s\n", nt_errstr(status)));
+ DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
if (!NT_STATUS_IS_OK(status)) {
- if (NT_STATUS_EQUAL(
- status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
+ if (!use_nt_status()
+ && NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_NAME_COLLISION)) {
/*
* Yes, in the DOS error code case we get a
* ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
@@ -3833,8 +3789,6 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- close_file(fsp, NORMAL_CLOSE);
-
outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
@@ -3906,7 +3860,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory)
The internals of the rmdir code - called elsewhere.
****************************************************************************/
-BOOL rmdir_internals(connection_struct *conn, char *directory)
+BOOL rmdir_internals(connection_struct *conn, const char *directory)
{
BOOL ok;
SMB_STRUCT_STAT st;
@@ -3979,10 +3933,13 @@ BOOL rmdir_internals(connection_struct *conn, char *directory)
}
}
- if (!ok)
- DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
+ if (!ok) {
+ DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
+ "%s\n", directory,strerror(errno)));
+ return False;
+ }
- return ok;
+ return True;
}
/****************************************************************************
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index c10662ab616..1805d67caf7 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -893,7 +893,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
}
}
- if (total_data && smb_action == FILE_WAS_CREATED) {
+ if (ea_list && smb_action == FILE_WAS_CREATED) {
status = set_ea(conn, fsp, fname, ea_list);
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp,ERROR_CLOSE);
@@ -4323,7 +4323,11 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
- inherit_access_acl(conn, fname, unixmode);
+ if (lp_inherit_perms(SNUM(conn))) {
+ inherit_access_acl(
+ conn, parent_dirname(fname),
+ fname, unixmode);
+ }
SSVAL(params,0,0);
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
@@ -4799,11 +4803,11 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
char *params = *pparams;
char *pdata = *ppdata;
pstring directory;
- int ret = -1;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
+ files_struct *fsp;
if (!CAN_WRITE(conn))
return ERROR_DOS(ERRSRV,ERRaccess);
@@ -4855,15 +4859,30 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- if (check_name(directory,conn)) {
- ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
- }
-
- if(ret < 0) {
+ if (!check_name(directory,conn)) {
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
+ return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,
+ ERRnoaccess);
+ }
+
+ status = open_directory(conn, directory, &sbuf,
+ FILE_READ_ATTRIBUTES, /* A stat open */
+ FILE_SHARE_NONE, /* Ignored */
+ FILE_CREATE, 0, NULL, &fsp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+#if 0
+ /* Do we need to do this here ? Need smbtorture test. JRA. */
+ if (!use_nt_status() && NT_STATUS_EQUAL(
+ status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
+ }
+#endif
+ return ERROR_NT(status);
}
+ close_file(fsp, NORMAL_CLOSE);
+
/* Try and set any given EA. */
if (ea_list) {
status = set_ea(conn, NULL, directory, ea_list);
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index 3ed56d3bf6f..a4ecff921af 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -307,31 +307,6 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_
}
/*******************************************************************
- vfs mkdir wrapper
-********************************************************************/
-
-int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode)
-{
- int ret;
- SMB_STRUCT_STAT sbuf;
-
- if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) {
-
- inherit_access_acl(conn, 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) &&
- !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode))
- SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode));
- }
- return ret;
-}
-
-/*******************************************************************
Check if an object exists in the vfs.
********************************************************************/