summaryrefslogtreecommitdiffstats
path: root/source/smbd/trans2.c
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2007-03-20 16:56:16 +0000
committerGerald Carter <jerry@samba.org>2007-03-20 16:56:16 +0000
commit651d5a89c59c107c05e789358624058e16af1b66 (patch)
treedfd29754255ea87b30eb16a06c505e42f98b9be3 /source/smbd/trans2.c
parent0f475ed1a387e37d477fd434c06ad5783c58adea (diff)
downloadsamba-651d5a89c59c107c05e789358624058e16af1b66.tar.gz
samba-651d5a89c59c107c05e789358624058e16af1b66.tar.xz
samba-651d5a89c59c107c05e789358624058e16af1b66.zip
r21889: * Pull from SAMBA-3_0_25 svn r21888
* Set version to 3.0.25pre2
Diffstat (limited to 'source/smbd/trans2.c')
-rw-r--r--source/smbd/trans2.c711
1 files changed, 567 insertions, 144 deletions
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 5bbd618231b..deb5db1bafe 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -5,6 +5,7 @@
Copyright (C) Stefan (metze) Metzmacher 2003
Copyright (C) Volker Lendecke 2005
Copyright (C) Steve French 2005
+ Copyright (C) James Peach 2007
Extensively modified by Andrew Tridgell, 1995
@@ -34,6 +35,16 @@ extern struct current_user current_user;
#define get_file_size(sbuf) ((sbuf).st_size)
#define DIR_ENTRY_SAFETY_MARGIN 4096
+static char *store_file_unix_basic(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf);
+
+static char *store_file_unix_basic_info2(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf);
+
/********************************************************************
Roundup a value to the nearest allocation roundup size boundary.
Only do this for Windows clients.
@@ -56,7 +67,7 @@ SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
account sparse files.
********************************************************************/
-SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
+SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
{
SMB_BIG_UINT ret;
@@ -1191,15 +1202,17 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
continue;
}
} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
+ pstring link_target;
/* Needed to show the msdfs symlinks as
* directories */
if(lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
- ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
-
- DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
+ ((ms_dfs_link = is_msdfs_link(conn, pathreal, link_target, &sbuf)) == True)) {
+ DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s "
+ "as a directory\n",
+ pathreal));
sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
} else {
@@ -1578,51 +1591,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
/* CIFS UNIX Extension. */
case SMB_FIND_FILE_UNIX:
- DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ case SMB_FIND_FILE_UNIX_INFO2:
p+= 4;
SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
- SOFF_T(p,0,get_file_size(sbuf)); /* File size 64 Bit */
- p+= 8;
-
- SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
- p+= 8;
-
- put_long_date_timespec(p,get_ctimespec(&sbuf)); /* Inode change Time 64 Bit */
- put_long_date_timespec(p+8,get_atimespec(&sbuf)); /* Last access time 64 Bit */
- put_long_date_timespec(p+16,get_mtimespec(&sbuf)); /* Last modification time 64 Bit */
- p+= 24;
-
- SIVAL(p,0,sbuf.st_uid); /* user id for the owner */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,sbuf.st_gid); /* group id of owner */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,unix_filetype(sbuf.st_mode));
- p+= 4;
-
- SIVAL(p,0,unix_dev_major(sbuf.st_rdev)); /* Major device number if type is device */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,unix_dev_minor(sbuf.st_rdev)); /* Minor device number if type is device */
- SIVAL(p,4,0);
- p+= 8;
-
- SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino); /* inode number */
- p+= 8;
- SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode)); /* Standard UNIX file permissions */
- SIVAL(p,4,0);
- p+= 8;
-
- SIVAL(p,0,sbuf.st_nlink); /* number of hard links */
- SIVAL(p,4,0);
- p+= 8;
+ if (info_level == SMB_FIND_FILE_UNIX) {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
+ p = store_file_unix_basic(conn, p,
+ NULL, &sbuf);
+ } else {
+ DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
+ p = store_file_unix_basic_info2(conn, p,
+ NULL, &sbuf);
+ }
len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
p += len;
@@ -1732,6 +1715,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
if (!lp_unix_extensions()) {
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
@@ -1745,7 +1729,13 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return ERROR_NT(ntstatus);
}
- RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
+ ntstatus = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory, &mask_contains_wcard);
+ if (!NT_STATUS_IS_OK(ntstatus)) {
+ if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(ntstatus);
+ }
ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
if (!NT_STATUS_IS_OK(ntstatus)) {
@@ -2037,6 +2027,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n",
case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
break;
case SMB_FIND_FILE_UNIX:
+ case SMB_FIND_FILE_UNIX_INFO2:
if (!lp_unix_extensions()) {
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
@@ -2232,7 +2223,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf
char **pparams, int total_params, char **ppdata, int total_data,
unsigned int max_data_bytes)
{
- char *pdata = *ppdata;
+ char *pdata;
char *params = *pparams;
uint16 info_level;
int data_len, len;
@@ -2530,6 +2521,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
CIFS_UNIX_POSIX_ACLS_CAP|
CIFS_UNIX_POSIX_PATHNAMES_CAP|
CIFS_UNIX_FCNTL_LOCKS_CAP|
+ CIFS_UNIX_EXTATTR_CAP|
CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
break;
@@ -2566,6 +2558,114 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
break;
}
+ case SMB_QUERY_POSIX_WHOAMI:
+ {
+ uint32_t flags = 0;
+ uint32_t sid_bytes;
+ int i;
+
+ if (!lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
+ if (max_data_bytes < 40) {
+ return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+ }
+
+ /* We ARE guest if global_sid_Builtin_Guests is
+ * in our list of SIDs.
+ */
+ if (nt_token_check_sid(&global_sid_Builtin_Guests,
+ current_user.nt_user_token)) {
+ flags |= SMB_WHOAMI_GUEST;
+ }
+
+ /* We are NOT guest if global_sid_Authenticated_Users
+ * is in our list of SIDs.
+ */
+ if (nt_token_check_sid(&global_sid_Authenticated_Users,
+ current_user.nt_user_token)) {
+ flags &= ~SMB_WHOAMI_GUEST;
+ }
+
+ /* NOTE: 8 bytes for UID/GID, irrespective of native
+ * platform size. This matches
+ * SMB_QUERY_FILE_UNIX_BASIC and friends.
+ */
+ data_len = 4 /* flags */
+ + 4 /* flag mask */
+ + 8 /* uid */
+ + 8 /* gid */
+ + 4 /* ngroups */
+ + 4 /* num_sids */
+ + 4 /* SID bytes */
+ + 4 /* pad/reserved */
+ + (current_user.ut.ngroups * 8)
+ /* groups list */
+ + (current_user.nt_user_token->num_sids *
+ SID_MAX_SIZE)
+ /* SID list */;
+
+ SIVAL(pdata, 0, flags);
+ SIVAL(pdata, 4, SMB_WHOAMI_MASK);
+ SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
+ SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
+
+
+ if (data_len >= max_data_bytes) {
+ /* Potential overflow, skip the GIDs and SIDs. */
+
+ SIVAL(pdata, 24, 0); /* num_groups */
+ SIVAL(pdata, 28, 0); /* num_sids */
+ SIVAL(pdata, 32, 0); /* num_sid_bytes */
+ SIVAL(pdata, 36, 0); /* reserved */
+
+ data_len = 40;
+ break;
+ }
+
+ SIVAL(pdata, 24, current_user.ut.ngroups);
+ SIVAL(pdata, 28,
+ current_user.nt_user_token->num_sids);
+
+ /* We walk the SID list twice, but this call is fairly
+ * infrequent, and I don't expect that it's performance
+ * sensitive -- jpeach
+ */
+ for (i = 0, sid_bytes = 0;
+ i < current_user.nt_user_token->num_sids; ++i) {
+ sid_bytes +=
+ sid_size(&current_user.nt_user_token->user_sids[i]);
+ }
+
+ /* SID list byte count */
+ SIVAL(pdata, 32, sid_bytes);
+
+ /* 4 bytes pad/reserved - must be zero */
+ SIVAL(pdata, 36, 0);
+ data_len = 40;
+
+ /* GID list */
+ for (i = 0; i < current_user.ut.ngroups; ++i) {
+ SBIG_UINT(pdata, data_len,
+ (SMB_BIG_UINT)current_user.ut.groups[i]);
+ data_len += 8;
+ }
+
+ /* SID list */
+ for (i = 0;
+ i < current_user.nt_user_token->num_sids; ++i) {
+ int sid_len =
+ sid_size(&current_user.nt_user_token->user_sids[i]);
+
+ sid_linearize(pdata + data_len, sid_len,
+ &current_user.nt_user_token->user_sids[i]);
+ data_len += sid_len;
+ }
+
+ break;
+ }
+
case SMB_MAC_QUERY_FS_INFO:
/*
* Thursby MAC extension... ONLY on NTFS filesystems
@@ -2871,7 +2971,7 @@ static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
static char *store_file_unix_basic(connection_struct *conn,
char *pdata,
files_struct *fsp,
- SMB_STRUCT_STAT *psbuf)
+ const SMB_STRUCT_STAT *psbuf)
{
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
@@ -2920,6 +3020,121 @@ static char *store_file_unix_basic(connection_struct *conn,
return pdata;
}
+/* Forward and reverse mappings from the UNIX_INFO2 file flags field and
+ * the chflags(2) (or equivalent) flags.
+ *
+ * XXX: this really should be behind the VFS interface. To do this, we would
+ * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
+ * Each VFS module could then implement it's own mapping as appropriate for the
+ * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
+ */
+static const struct {unsigned stat_fflag; unsigned smb_fflag;}
+ info2_flags_map[] =
+{
+#ifdef UF_NODUMP
+ { UF_NODUMP, EXT_DO_NOT_BACKUP },
+#endif
+
+#ifdef UF_IMMUTABLE
+ { UF_IMMUTABLE, EXT_IMMUTABLE },
+#endif
+
+#ifdef UF_APPEND
+ { UF_APPEND, EXT_OPEN_APPEND_ONLY },
+#endif
+
+#ifdef UF_HIDDEN
+ { UF_HIDDEN, EXT_HIDDEN },
+#endif
+
+ /* Do not remove. We need to guarantee that this array has at least one
+ * entry to build on HP-UX.
+ */
+ { 0, 0 }
+
+};
+
+static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
+ uint32 *smb_fflags, uint32 *smb_fmask)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+ *smb_fmask |= info2_flags_map[i].smb_fflag;
+ if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
+ *smb_fflags |= info2_flags_map[i].smb_fflag;
+ }
+ }
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
+ const uint32 smb_fflags,
+ const uint32 smb_fmask,
+ int *stat_fflags)
+{
+#ifdef HAVE_STAT_ST_FLAGS
+ uint32 max_fmask = 0;
+ int i;
+
+ *stat_fflags = psbuf->st_flags;
+
+ /* For each flags requested in smb_fmask, check the state of the
+ * corresponding flag in smb_fflags and set or clear the matching
+ * stat flag.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
+ max_fmask |= info2_flags_map[i].smb_fflag;
+ if (smb_fmask & info2_flags_map[i].smb_fflag) {
+ if (smb_fflags & info2_flags_map[i].smb_fflag) {
+ *stat_fflags |= info2_flags_map[i].stat_fflag;
+ } else {
+ *stat_fflags &= ~info2_flags_map[i].stat_fflag;
+ }
+ }
+ }
+
+ /* If smb_fmask is asking to set any bits that are not supported by
+ * our flag mappings, we should fail.
+ */
+ if ((smb_fmask & max_fmask) != smb_fmask) {
+ return False;
+ }
+
+ return True;
+#else
+ return False;
+#endif /* HAVE_STAT_ST_FLAGS */
+}
+
+
+/* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
+ * of file flags and birth (create) time.
+ */
+static char *store_file_unix_basic_info2(connection_struct *conn,
+ char *pdata,
+ files_struct *fsp,
+ const SMB_STRUCT_STAT *psbuf)
+{
+ uint32 file_flags = 0;
+ uint32 flags_mask = 0;
+
+ pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
+
+ /* Create (birth) time 64 bit */
+ put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
+ pdata += 8;
+
+ map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
+ SIVAL(pdata, 0, file_flags); /* flags */
+ SIVAL(pdata, 4, flags_mask); /* mask */
+ pdata += 8;
+
+ return pdata;
+}
+
/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
file name or file id).
@@ -2970,6 +3185,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
if(fsp && (fsp->fake_file_handle)) {
/*
* This is actually for the QUOTA_FAKE_FILE --metze
@@ -3026,12 +3245,22 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
+ if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
+ return ERROR_NT(NT_STATUS_INVALID_LEVEL);
+ }
+
srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
@@ -3175,18 +3404,16 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
allocation_size = get_allocation_size(conn,fsp,&sbuf);
if (fsp) {
- if (fsp->pending_modtime) {
+ if (!null_timespec(fsp->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- mtime_ts.tv_sec = fsp->pending_modtime;
- mtime_ts.tv_nsec = 0;
+ mtime_ts = fsp->pending_modtime;
}
} else {
/* Do we have this path open ? */
files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
- if (fsp1 && fsp1->pending_modtime) {
+ if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- mtime_ts.tv_sec = fsp1->pending_modtime;
- mtime_ts.tv_nsec = 0;
+ mtime_ts = fsp1->pending_modtime;
}
if (fsp1 && fsp1->initial_allocation_size) {
allocation_size = get_allocation_size(conn, fsp1, &sbuf);
@@ -3539,6 +3766,22 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
break;
+ case SMB_QUERY_FILE_UNIX_INFO2:
+
+ pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
+ data_size = PTR_DIFF(pdata,(*ppdata));
+
+ {
+ int i;
+ DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
+
+ for (i=0; i<100; i++)
+ DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
+ DEBUG(4,("\n"));
+ }
+
+ break;
+
case SMB_QUERY_FILE_UNIX_LINK:
{
pstring buffer;
@@ -3743,17 +3986,22 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
return status;
}
+ status = check_name(conn, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* source must already exist. */
if (!VALID_STAT(sbuf1)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- status = check_name(conn, oldname);
+ status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
+ return status;
}
- status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
+ status = check_name(conn, newname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -3763,11 +4011,6 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- status = check_name(conn, newname);
- if (!NT_STATUS_IS_OK(status)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* No links from a directory. */
if (S_ISDIR(sbuf1.st_mode)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
@@ -3798,7 +4041,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
files_struct *fsp,
const char *fname,
const SMB_STRUCT_STAT *psbuf,
- struct utimbuf tvs)
+ struct timespec ts[2])
{
uint32 action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -3810,26 +4053,30 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_mtime(tvs.actime)) {
- tvs.actime = psbuf->st_atime;
+ if (null_timespec(ts[0])) {
+ ts[0] = get_atimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = psbuf->st_mtime;
+ if (null_timespec(ts[1])) {
+ ts[1] = get_mtimespec(psbuf);
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
- DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
- DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
+ DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
+ DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
/*
* Try and set the times of this file if
* they are different from the current values.
*/
- if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
- return NT_STATUS_OK;
+ {
+ struct timespec mts = get_mtimespec(psbuf);
+ struct timespec ats = get_atimespec(psbuf);
+ if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
+ return NT_STATUS_OK;
+ }
}
if(fsp != NULL) {
@@ -3843,15 +4090,16 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
* away and will set it on file close and after a write. JRA.
*/
- if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
- DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
- fsp_set_pending_modtime(fsp, tvs.modtime);
+ if (!null_timespec(ts[1])) {
+ DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+ time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ fsp_set_pending_modtime(fsp, ts[1]);
}
}
DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
- if(file_utime(conn, fname, &tvs)!=0) {
+ if(file_ntimes(conn, fname, ts)!=0) {
return map_nt_error_from_unix(errno);
}
if (action != 0) {
@@ -4030,6 +4278,12 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
delete_on_close = (CVAL(pdata,0) ? True : False);
dosmode = dos_mode(conn, fname, psbuf);
+ DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
+ "delete_on_close = %u\n",
+ fsp->fsp_name,
+ (unsigned int)dosmode,
+ (unsigned int)delete_on_close ));
+
status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
if (!NT_STATUS_IS_OK(status)) {
@@ -4132,7 +4386,6 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
pstring rel_name;
char *last_dirp = NULL;
- unix_format(link_target);
if (*link_target == '/') {
/* No absolute paths allowed. */
return NT_STATUS_ACCESS_DENIED;
@@ -4186,7 +4439,10 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
return status;
}
- RESOLVE_DFSPATH_STATUS(oldname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
fname, oldname));
@@ -4211,6 +4467,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
uint32 len;
pstring newname;
pstring base_name;
+ BOOL dest_has_wcard = False;
NTSTATUS status = NT_STATUS_OK;
char *p;
@@ -4226,12 +4483,15 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+ srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
+ status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
/* Check the new name has no '/' characters. */
if (strchr_m(newname, '/')) {
@@ -4255,7 +4515,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
} else {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, newname ));
- status = rename_internals(conn, fname, base_name, 0, overwrite, False);
+ status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
}
return status;
@@ -4305,6 +4565,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
+ DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
+ fname ? fname : fsp->fsp_name,
+ (unsigned int)num_file_acls,
+ (unsigned int)num_def_acls));
+
if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
return map_nt_error_from_unix(errno);
@@ -4386,6 +4651,14 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
#endif /* HAVE_LONGLONG */
+ DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
+ "lock_pid = %u, count = %.0f, offset = %.0f\n",
+ fsp->fsp_name,
+ (unsigned int)lock_type,
+ (unsigned int)lock_pid,
+ (double)count,
+ (double)offset ));
+
if (lock_type == UNLOCK_LOCK) {
status = do_unlock(fsp,
lock_pid,
@@ -4439,22 +4712,25 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
const char *fname,
const SMB_STRUCT_STAT *psbuf)
{
- struct utimbuf tvs;
+ struct timespec ts[2];
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
/* access time */
- tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
+ ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
/* write time */
- tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
+
+ DEBUG(10,("smb_set_info_standard: file %s\n",
+ fname ? fname : fsp->fsp_name ));
return smb_set_file_time(conn,
fsp,
fname,
psbuf,
- tvs);
+ ts);
}
/****************************************************************************
@@ -4469,10 +4745,10 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
SMB_STRUCT_STAT *psbuf)
{
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
- time_t write_time;
- time_t changed_time;
+ struct timespec write_time;
+ struct timespec changed_time;
uint32 dosmode = 0;
- struct utimbuf tvs;
+ struct timespec ts[2];
NTSTATUS status = NT_STATUS_OK;
if (total_data < 36) {
@@ -4492,26 +4768,31 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
/* Ignore create time at offset pdata. */
/* access time */
- tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
+ ts[0] = interpret_long_date(pdata+8);
- write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
- changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
+ write_time = interpret_long_date(pdata+16);
+ changed_time = interpret_long_date(pdata+24);
- tvs.modtime = MIN(write_time, changed_time);
+ /* mtime */
+ ts[1] = timespec_min(&write_time, &changed_time);
- if (write_time > tvs.modtime && write_time != (time_t)-1) {
- tvs.modtime = write_time;
+ if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
+ ts[1] = write_time;
}
+
/* Prefer a defined time to an undefined one. */
- if (null_mtime(tvs.modtime)) {
- tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
+ if (null_timespec(ts[1])) {
+ ts[1] = null_timespec(write_time) ? changed_time : write_time;
}
+ DEBUG(10,("smb_set_file_basic_info: file %s\n",
+ fname ? fname : fsp->fsp_name ));
+
return smb_set_file_time(conn,
fsp,
fname,
psbuf,
- tvs);
+ ts);
}
/****************************************************************************
@@ -4725,7 +5006,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
const char *fname,
SMB_STRUCT_STAT *psbuf)
{
- struct utimbuf tvs;
+ struct timespec ts[2];
uint32 raw_unixmode;
mode_t unixmode;
SMB_OFF_T size = 0;
@@ -4752,8 +5033,8 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
#endif /* LARGE_SMB_OFF_T */
}
- tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
- tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
+ ts[0] = interpret_long_date(pdata+24); /* access_time */
+ ts[1] = interpret_long_date(pdata+32); /* modification_time */
set_owner = (uid_t)IVAL(pdata,40);
set_grp = (gid_t)IVAL(pdata,48);
raw_unixmode = IVAL(pdata,84);
@@ -4796,8 +5077,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
/* Ensure we don't try and change anything else. */
raw_unixmode = SMB_MODE_NO_CHANGE;
size = get_file_size(*psbuf);
- tvs.modtime = psbuf->st_mtime;
- tvs.actime = psbuf->st_atime;
+ ts[0] = get_atimespec(psbuf);
+ ts[1] = get_mtimespec(psbuf);
/*
* We continue here as we might want to change the
* owner uid/gid.
@@ -4876,7 +5157,68 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
fsp,
fname,
psbuf,
- tvs);
+ ts);
+}
+
+/****************************************************************************
+ Deal with SMB_SET_FILE_UNIX_INFO2.
+****************************************************************************/
+
+static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
+ const char *pdata,
+ int total_data,
+ files_struct *fsp,
+ const char *fname,
+ SMB_STRUCT_STAT *psbuf)
+{
+ NTSTATUS status;
+ uint32 smb_fflags;
+ uint32 smb_fmask;
+
+ if (total_data < 116) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* Start by setting all the fields that are common between UNIX_BASIC
+ * and UNIX_INFO2.
+ */
+ status = smb_set_file_unix_basic(conn, pdata, total_data,
+ fsp, fname, psbuf);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ smb_fflags = IVAL(pdata, 108);
+ smb_fmask = IVAL(pdata, 112);
+
+ /* NB: We should only attempt to alter the file flags if the client
+ * sends a non-zero mask.
+ */
+ if (smb_fmask != 0) {
+ int stat_fflags = 0;
+
+ if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
+ &stat_fflags)) {
+ /* Client asked to alter a flag we don't understand. */
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (fsp && fsp->fh->fd != -1) {
+ /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
+ return NT_STATUS_NOT_SUPPORTED;
+ } else {
+ if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+ }
+
+ /* XXX: need to add support for changing the create_time here. You
+ * can do this for paths on Darwin with setattrlist(2). The right way
+ * to hook this up is probably by extending the VFS utimes interface.
+ */
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -4896,13 +5238,16 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
mode_t unixmode = (mode_t)0;
files_struct *fsp = NULL;
uint16 info_level_return = 0;
+ int info;
char *pdata = *ppdata;
- if (total_data < 10) {
+ if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
}
raw_unixmode = IVAL(pdata,8);
+ /* Next 4 bytes are not yet defined. */
+
status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -4910,6 +5255,9 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
+ fname, (unsigned int)unixmode ));
+
status = open_directory(conn,
fname,
psbuf,
@@ -4918,19 +5266,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
FILE_CREATE,
0,
mod_unixmode,
- NULL,
+ &info,
&fsp);
if (NT_STATUS_IS_OK(status)) {
close_file(fsp, NORMAL_CLOSE);
}
- info_level_return = SVAL(pdata,12);
+ info_level_return = SVAL(pdata,16);
if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
+ *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
} else {
- *pdata_return_size = 8;
+ *pdata_return_size = 12;
}
/* Realloc the data size */
@@ -4941,15 +5291,21 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
}
SSVAL(pdata,0,NO_OPLOCK_RETURN);
- SSVAL(pdata,2,0);
-
- if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,6,0); /* Padding. */
- store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
- } else {
- SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,6,0); /* Padding. */
+ SSVAL(pdata,2,0); /* No fnum. */
+ SIVAL(pdata,4,info); /* Was directory created. */
+
+ switch (info_level_return) {
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* Padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* Padding. */
}
return status;
@@ -4982,7 +5338,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
int info = 0;
uint16 info_level_return = 0;
- if (total_data < 14) {
+ if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
}
@@ -5034,6 +5390,8 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
}
raw_unixmode = IVAL(pdata,8);
+ /* Next 4 bytes are not yet defined. */
+
status = unix_perms_from_wire(conn,
psbuf,
raw_unixmode,
@@ -5056,6 +5414,11 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
mod_unixmode |= FILE_FLAG_NO_BUFFERING;
}
+ DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
+ fname,
+ (unsigned int)wire_open_mode,
+ (unsigned int)unixmode ));
+
status = open_file_ntcreate(conn,
fname,
psbuf,
@@ -5080,12 +5443,16 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
extended_oplock_granted = True;
}
- info_level_return = SVAL(pdata,12);
+ info_level_return = SVAL(pdata,16);
+ /* Allocate the correct return size. */
+
if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
+ *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
+ } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
+ *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
} else {
- *pdata_return_size = 8;
+ *pdata_return_size = 12;
}
/* Realloc the data size */
@@ -5109,13 +5476,20 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
}
SSVAL(pdata,2,fsp->fnum);
- if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
- SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
- SSVAL(pdata,6,0); /* padding. */
- store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
- } else {
- SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
- SSVAL(pdata,6,0); /* padding. */
+ SIVAL(pdata,4,info); /* Was file created etc. */
+
+ switch (info_level_return) {
+ case SMB_QUERY_FILE_UNIX_BASIC:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
+ case SMB_QUERY_FILE_UNIX_INFO2:
+ SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
+ SSVAL(pdata,10,0); /* padding. */
+ store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
+ default:
+ SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
+ SSVAL(pdata,10,0); /* padding. */
}
return NT_STATUS_OK;
}
@@ -5132,12 +5506,28 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
{
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
+ uint16 flags = 0;
int info = 0;
+ if (total_data < 2) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ flags = SVAL(pdata,0);
+
if (!VALID_STAT(*psbuf)) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
+ if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
+ !VALID_STAT_OF_DIR(*psbuf)) {
+ return NT_STATUS_NOT_A_DIRECTORY;
+ }
+
+ DEBUG(10,("smb_posix_unlink: %s %s\n",
+ (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
+ fname));
+
if (VALID_STAT_OF_DIR(*psbuf)) {
status = open_directory(conn,
fname,
@@ -5150,17 +5540,34 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
&info,
&fsp);
} else {
+ char del = 1;
+
status = open_file_ntcreate(conn,
fname,
psbuf,
DELETE_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
- FILE_DELETE_ON_CLOSE,
+ 0,
FILE_FLAG_POSIX_SEMANTICS|0777,
- INTERNAL_OPEN_ONLY,
+ 0, /* No oplock, but break existing ones. */
&info,
&fsp);
+ /*
+ * For file opens we must set the delete on close
+ * after the open.
+ */
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = smb_set_file_disposition_info(conn,
+ &del,
+ 1,
+ fsp,
+ fname,
+ psbuf);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -5251,13 +5658,24 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+ status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
+ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
+ }
+ return ERROR_NT(status);
+ }
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return ERROR_NT(status);
+ }
+
/*
* For CIFS UNIX extensions the target name may not exist.
*/
@@ -5266,12 +5684,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
return UNIXERROR(ERRDOS,ERRbadpath);
}
-
- status = check_name(conn, fname);
- if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
-
}
if (!CAN_WRITE(conn)) {
@@ -5294,9 +5706,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
SSVAL(params,0,0);
- if (fsp && fsp->pending_modtime) {
+ if (fsp && !null_timespec(fsp->pending_modtime)) {
/* the pending modtime overrides the current modtime */
- sbuf.st_mtime = fsp->pending_modtime;
+ set_mtimespec(&sbuf, fsp->pending_modtime);
}
switch (info_level) {
@@ -5417,6 +5829,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
break;
}
+ case SMB_SET_FILE_UNIX_INFO2:
+ {
+ status = smb_set_file_unix_info2(conn,
+ pdata,
+ total_data,
+ fsp,
+ fname,
+ &sbuf);
+ break;
+ }
+
case SMB_SET_FILE_UNIX_LINK:
{
if (tran_call != TRANSACT2_SETPATHINFO) {
@@ -5576,6 +5999,12 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(status);
}
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
+ return ERROR_NT(status);
+ }
+
/* Any data in this call is an EA list. */
if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
@@ -5607,12 +6036,6 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- status = check_name(conn, directory);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
- return ERROR_NT(status);
- }
-
status = create_directory(conn, directory);
if (!NT_STATUS_IS_OK(status)) {