Do this by fd if possible.
****************************************************************************/
-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);
}
/****************************************************************************
static NTSTATUS open_file(files_struct *fsp,
connection_struct *conn,
- const char *fname,
+ const char *parent_dir,
+ const char *name,
+ const char *path,
SMB_STRUCT_STAT *psbuf,
int flags,
mode_t unx_mode,
if (!CAN_WRITE(conn)) {
/* It's a read-only share - fail if we wanted to write. */
if(accmode != O_RDONLY) {
- DEBUG(3,("Permission denied opening %s\n",fname));
+ DEBUG(3,("Permission denied opening %s\n", path));
return NT_STATUS_ACCESS_DENIED;
} else if(flags & O_CREAT) {
/* We don't want to write - but we must make sure that
if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
DEBUG(10,("open_file: truncate requested on read-only open "
- "for file %s\n",fname ));
+ "for file %s\n", path));
local_flags = (flags & ~O_ACCMODE)|O_RDWR;
}
/* Don't create files with Microsoft wildcard characters. */
if ((local_flags & O_CREAT) && !file_existed &&
- ms_has_wild(fname)) {
+ ms_has_wild(path)) {
return NT_STATUS_OBJECT_NAME_INVALID;
}
/* Actually do the open */
- if (!fd_open(conn, fname, fsp, local_flags, unx_mode)) {
+ if (!fd_open(conn, path, fsp, local_flags, unx_mode)) {
DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
"(flags=%d)\n",
- fname,strerror(errno),local_flags,flags));
+ path,strerror(errno),local_flags,flags));
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, path,
+ unx_mode);
+ }
+
+ /* Change the owner if required. */
+ if (lp_inherit_owner(SNUM(conn))) {
+ change_file_owner_to_parent(conn, parent_dir,
+ fsp);
+ }
+
+ notify_action(conn, parent_dir, name, -1,
+ NOTIFY_ACTION_ADDED);
}
} else {
int ret;
if (fsp->fh->fd == -1) {
- ret = SMB_VFS_STAT(conn, fname, psbuf);
+ ret = SMB_VFS_STAT(conn, path, psbuf);
} else {
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
/* If we have an fd, this stat should succeed. */
if (ret == -1) {
DEBUG(0,("Error doing fstat on open file %s "
- "(%s)\n", fname,strerror(errno) ));
+ "(%s)\n", path,strerror(errno) ));
}
}
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = False;
fsp->is_stat = False;
- if (conn->aio_write_behind_list &&
- is_in_path(fname, conn->aio_write_behind_list, conn->case_sensitive)) {
+ if (conn->aio_write_behind_list
+ && is_in_path(path, conn->aio_write_behind_list,
+ conn->case_sensitive)) {
fsp->aio_write_behind = True;
}
- string_set(&fsp->fsp_name,fname);
+ string_set(&fsp->fsp_name, path);
fsp->wcp = NULL; /* Write cache pointer. */
DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
if (is_deferred_open_entry(share_entry) &&
!open_was_deferred(share_entry->op_mid)) {
pstring str;
- DEBUG(0, ("Got a deferred entry without a request: "
- "PANIC: %s\n", share_mode_str(num, share_entry)));
+ pstr_sprintf(str, "Got a deferred entry without a request: "
+ "PANIC: %s\n", share_mode_str(num, share_entry));
smb_panic(str);
}
BOOL valid_entry = False;
BOOL delay_it = False;
BOOL have_level2 = False;
+ BOOL ret;
+ char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
if (oplock_request & INTERNAL_OPEN_ONLY) {
fsp->oplock_type = NO_OPLOCK;
fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
}
- if (delay_it) {
- BOOL ret;
- char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
+ if (!delay_it) {
+ return False;
+ }
- DEBUG(10, ("Sending break request to PID %s\n",
- procid_str_static(&exclusive->pid)));
- exclusive->op_mid = get_current_mid();
+ /*
+ * Send a break message to the oplock holder and delay the open for
+ * our client.
+ */
- /* Create the message. */
- share_mode_entry_to_message(msg, exclusive);
+ DEBUG(10, ("Sending break request to PID %s\n",
+ procid_str_static(&exclusive->pid)));
+ exclusive->op_mid = get_current_mid();
- /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We don't
- want this set in the share mode struct pointed to by lck. */
+ /* Create the message. */
+ share_mode_entry_to_message(msg, exclusive);
- if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
- SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
- }
+ /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We
+ don't want this set in the share mode struct pointed to by lck. */
- become_root();
- ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
- msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
- unbecome_root();
- if (!ret) {
- DEBUG(3, ("Could not send oplock break message\n"));
- }
+ if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
+ SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
+ }
+
+ ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
+ if (!ret) {
+ DEBUG(3, ("Could not send oplock break message\n"));
}
- return delay_it;
+ return True;
}
static BOOL request_timed_out(struct timeval request_time,
srv_defer_sign_response(mid);
}
-/****************************************************************************
- Set a kernel flock on a file for NFS interoperability.
- This requires a patch to Linux.
-****************************************************************************/
-
-static void kernel_flock(files_struct *fsp, uint32 share_mode)
-{
-#if HAVE_KERNEL_SHARE_MODES
- int kernel_mode = 0;
- if (share_mode == FILE_SHARE_WRITE) {
- kernel_mode = LOCK_MAND|LOCK_WRITE;
- } else if (share_mode == FILE_SHARE_READ) {
- kernel_mode = LOCK_MAND|LOCK_READ;
- } else if (share_mode == FILE_SHARE_NONE) {
- kernel_mode = LOCK_MAND;
- }
- if (kernel_mode) {
- flock(fsp->fh->fd, kernel_mode);
- }
-#endif
- ;
-}
/****************************************************************************
On overwrite open ensure that the attributes match.
struct share_mode_lock *lck = NULL;
uint32 open_access_mask = access_mask;
NTSTATUS status;
+ int ret_flock;
+ char *parent_dir;
+ const char *newname;
if (conn->printer) {
/*
DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
- return print_fsp_open(conn, fname, &fsp);
+ 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 "
remove_deferred_open_smb_message(mid);
}
- if (!check_name(fname,conn)) {
- return map_nt_error_from_unix(errno);
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
/* 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()) {
*/
if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) {
- flags = O_RDWR;
+ /* DENY_DOS opens are always underlying read-write on the
+ file handle, no matter what the requested access mask
+ says. */
+ if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) ||
+ access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) {
+ flags = O_RDWR;
+ } else {
+ flags = O_WRONLY;
+ }
} else {
flags = O_RDONLY;
}
if (flags & O_RDWR) {
can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
+ } else if (flags & O_WRONLY) {
+ can_access_mask = FILE_WRITE_DATA;
} else {
can_access_mask = FILE_READ_DATA;
}
- if (((flags & O_RDWR) && !CAN_WRITE(conn)) ||
+ if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
!can_access_file(conn,fname,psbuf,can_access_mask)) {
can_access = False;
}
*/
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;
}
* 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, newname, fname, psbuf,
+ flags|flags2, unx_mode, access_mask,
+ open_access_mask);
if (!NT_STATUS_IS_OK(fsp_open)) {
if (lck != NULL) {
these only read them. Nobody but Samba can ever set a deny
mode and we have already checked our more authoritative
locking database for permission to set this deny mode. If
- the kernel refuses the operations then the kernel is wrong */
+ the kernel refuses the operations then the kernel is wrong.
+ note that GPFS supports it as well - jmcd */
+
+ ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access);
+ if(ret_flock == -1 ){
- kernel_flock(fsp, share_access);
+ TALLOC_FREE(lck);
+ fd_close(conn, fsp);
+ file_free(fsp);
+
+ return NT_STATUS_SHARING_VIOLATION;
+ }
/*
* At this point onwards, we can guarentee that the share entry
}
} 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) {
return status;
}
/* Note that here we set the *inital* delete on close flag,
- not the regular one. */
- set_delete_on_close_token(lck, ¤t_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
}
/* Files should be initially set as archive */
lp_store_dos_attributes(SNUM(conn))) {
file_set_dosmode(conn, fname,
new_dos_attributes | aARCH, NULL,
- True);
+ parent_dir);
}
}
/* 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, NULL, fname, psbuf, O_WRONLY, 0,
+ FILE_WRITE_DATA, FILE_WRITE_DATA);
/*
* This is not a user visible file open.
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;
+ NTSTATUS status;
+
+ 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;
+ }
+
+ status = check_name(conn, name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ 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);
+ }
+
+ notify_action(conn, parent_dir, dirname, FILE_NOTIFY_CHANGE_DIR_NAME,
+ NOTIFY_ACTION_ADDED);
+
+ return NT_STATUS_OK;
+}
+
/****************************************************************************
Open a directory from an NT SMB call.
****************************************************************************/
{
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;
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:
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);
always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
if (create_options & FILE_DELETE_ON_CLOSE) {
status = can_set_delete_on_close(fsp, True, 0);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
TALLOC_FREE(lck);
file_free(fsp);
return status;
}
- set_delete_on_close_token(lck, ¤t_user.ut);
- lck->initial_delete_on_close = True;
- lck->modified = True;
+ if (NT_STATUS_IS_OK(status)) {
+ /* Note that here we set the *inital* delete on close flag,
+ not the regular one. The magic gets handled in close. */
+ fsp->initial_delete_on_close = True;
+ }
}
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;
}
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).
****************************************************************************/
-NTSTATUS open_file_stat(connection_struct *conn, char *fname,
+NTSTATUS open_file_stat(connection_struct *conn, const char *fname,
SMB_STRUCT_STAT *psbuf, files_struct **result)
{
files_struct *fsp = NULL;
smbd process.
****************************************************************************/
-void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len)
+void msg_file_was_renamed(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
files_struct *fsp;
char *frm = (char *)buf;