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_owner_to_parent(connection_struct *conn,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
{
const char *parent_path = parent_dirname(fname);
SMB_STRUCT_STAT parent_st;
}
/* Inherit the ACL if the file was created. */
- if ((local_flags & O_CREAT) && !file_existed) {
+ if ((local_flags & O_CREAT)
+ && !file_existed
+ && lp_inherit_perms(SNUM(conn))) {
inherit_access_acl(conn, fname, unx_mode);
}
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);
}
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;
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);
}
/* We add aARCH to this as this mode is only used if the file is
*/
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;
}
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 */
- kernel_flock(fsp, share_access);
+ ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access);
+ if(ret_flock == -1 ){
+
+ 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
return ret;
}
+static NTSTATUS mkdir_internal(connection_struct *conn, const char *name)
+{
+ SMB_STRUCT_STAT sbuf;
+ int ret= -1;
+ mode_t mode;
+
+ 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);
+ }
+
+ mode = unix_mode(conn, aDIR, name, True);
+
+ if ((ret=SMB_VFS_MKDIR(conn, name, mode)) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+
+ if (lp_inherit_perms(SNUM(conn))) {
+ 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) == 0)
+ && (mode & ~sbuf.st_mode)) {
+ SMB_VFS_CHMOD(conn, name,
+ sbuf.st_mode | (mode & ~sbuf.st_mode));
+ }
+
+ 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;
- }
+ /*
+ * Don't do anything. The check for existence is done
+ * futher down.
+ */
info = FILE_WAS_OPENED;
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);
+ 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);
+
+ 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. */
- /* 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(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);
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;