#include "system/filesys.h"
#include "smbd/smbd.h"
-static int linux_xfs_sgid_mkdir(vfs_handle_struct *handle,
+static int linux_xfs_sgid_mkdirat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
mode_t mode)
{
- struct smb_filename fname = { 0, };
+ struct smb_filename *dname = NULL;
+ struct smb_filename *fname = NULL;
int mkdir_res;
int res;
+ NTSTATUS status;
- DEBUG(10, ("Calling linux_xfs_sgid_mkdir(%s)\n", smb_fname->base_name));
+ DEBUG(10, ("Calling linux_xfs_sgid_mkdirat(%s)\n",
+ smb_fname->base_name));
- mkdir_res = SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
+ mkdir_res = SMB_VFS_NEXT_MKDIRAT(handle,
+ dirfsp,
+ smb_fname,
+ mode);
if (mkdir_res == -1) {
- DEBUG(10, ("SMB_VFS_NEXT_MKDIR returned error: %s\n",
+ DEBUG(10, ("SMB_VFS_NEXT_MKDIRAT returned error: %s\n",
strerror(errno)));
return mkdir_res;
}
- if (!parent_dirname(talloc_tos(),
- smb_fname->base_name,
- &fname.base_name,
- NULL)) {
- DEBUG(1, ("parent_dirname failed\n"));
+ fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname);
+ if (fname == NULL) {
+ return -1;
+ }
+
+ status = SMB_VFS_PARENT_PATHNAME(handle->conn,
+ talloc_tos(),
+ fname,
+ &dname,
+ NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_WARNING("SMB_VFS_PARENT_PATHNAME() failed with %s\n",
+ nt_errstr(status));
/* return success, we did the mkdir */
return mkdir_res;
}
- res = SMB_VFS_NEXT_STAT(handle, &fname);
+ res = SMB_VFS_NEXT_STAT(handle, dname);
if (res == -1) {
- DEBUG(10, ("NEXT_STAT(%s) failed: %s\n", fname.base_name,
- strerror(errno)));
+ DBG_DEBUG("NEXT_STAT(%s) failed: %s\n",
+ smb_fname_str_dbg(dname),
+ strerror(errno));
/* return success, we did the mkdir */
return mkdir_res;
}
- TALLOC_FREE(fname.base_name);
- if ((fname.st.st_ex_mode & S_ISGID) == 0) {
+ if ((dname->st.st_ex_mode & S_ISGID) == 0) {
/* No SGID to inherit */
DEBUG(10, ("No SGID to inherit\n"));
+ TALLOC_FREE(dname);
return mkdir_res;
}
+ TALLOC_FREE(dname);
- fname.base_name = discard_const_p(char, smb_fname->base_name);
-
- res = SMB_VFS_NEXT_STAT(handle, &fname);
+ res = SMB_VFS_NEXT_STAT(handle, fname);
if (res == -1) {
- DEBUG(2, ("Could not stat just created dir %s: %s\n",
- smb_fname->base_name,
- strerror(errno)));
+ DBG_NOTICE("Could not stat just created dir %s: %s\n",
+ smb_fname_str_dbg(fname),
+ strerror(errno));
/* return success, we did the mkdir */
+ TALLOC_FREE(fname);
return mkdir_res;
}
- fname.st.st_ex_mode |= S_ISGID;
- fname.st.st_ex_mode &= ~S_IFDIR;
+ fname->st.st_ex_mode |= S_ISGID;
+ fname->st.st_ex_mode &= ~S_IFDIR;
/*
* Yes, we have to do this as root. If you do it as
* return success. What can you do...
*/
become_root();
- res = SMB_VFS_NEXT_CHMOD(handle,
- smb_fname,
- fname.st.st_ex_mode);
+ res = SMB_VFS_NEXT_FCHMOD(handle, smb_fname->fsp, fname->st.st_ex_mode);
unbecome_root();
if (res == -1) {
- DEBUG(2, ("CHMOD(%s, %o) failed: %s\n", smb_fname->base_name,
- (int)fname.st.st_ex_mode, strerror(errno)));
+ DBG_NOTICE("CHMOD(%s, %o) failed: %s\n",
+ smb_fname_str_dbg(fname),
+ (int)fname->st.st_ex_mode,
+ strerror(errno));
/* return success, we did the mkdir */
+ TALLOC_FREE(fname);
return mkdir_res;
}
- return mkdir_res;
-}
-static int linux_xfs_sgid_chmod_acl(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- mode_t mode)
-{
- errno = ENOSYS;
- return -1;
+ TALLOC_FREE(fname);
+ return mkdir_res;
}
static struct vfs_fn_pointers linux_xfs_sgid_fns = {
- .mkdir_fn = linux_xfs_sgid_mkdir,
- .chmod_acl_fn = linux_xfs_sgid_chmod_acl,
+ .mkdirat_fn = linux_xfs_sgid_mkdirat,
};
-NTSTATUS vfs_linux_xfs_sgid_init(TALLOC_CTX *);
+static_decl_vfs;
NTSTATUS vfs_linux_xfs_sgid_init(TALLOC_CTX *ctx)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION,