summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2004-04-02 18:46:19 +0000
committerJeremy Allison <jra@samba.org>2004-04-02 18:46:19 +0000
commit722aa118c66b020c2b9f2b595e1af50429f13986 (patch)
tree8308634feee7548ab22ccab11cb4818f2e9d9b62 /source3/smbd
parent044c6f513dca21d4fc01db4a686c75d43d4952d2 (diff)
downloadsamba-722aa118c66b020c2b9f2b595e1af50429f13986.tar.gz
samba-722aa118c66b020c2b9f2b595e1af50429f13986.tar.bz2
samba-722aa118c66b020c2b9f2b595e1af50429f13986.zip
Added per-share parameter "store dos attributes". When set, will store
dos attributes in an EA. Based on an original patch from tridge, but modified somewhat to cover all cases. Jeremy. (This used to be commit ed653cd468213e0be901bc654aa3748ce5837947)
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/dir.c4
-rw-r--r--source3/smbd/dosmode.c129
-rw-r--r--source3/smbd/fake_file.c8
-rw-r--r--source3/smbd/fileio.c5
-rw-r--r--source3/smbd/nttrans.c23
-rw-r--r--source3/smbd/open.c81
-rw-r--r--source3/smbd/posix_acls.c2
-rw-r--r--source3/smbd/reply.c48
-rw-r--r--source3/smbd/trans2.c16
9 files changed, 213 insertions, 103 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index bbd79e1659..06ef23ab8c 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -707,7 +707,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
if(S_ISDIR(pst->st_mode))
fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- unix_mode(conn,aRONLY|aDIR, name), &smb_action);
+ &smb_action);
else
fsp = open_file_stat(conn, name, pst);
@@ -763,7 +763,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
return True;
else
fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp)
return False;
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 1369c46b2f..d7dc63bb2f 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -45,11 +45,12 @@
mode_t unix_mode(connection_struct *conn, int dosmode, const char *fname)
{
- mode_t result = (S_IRUSR | S_IRGRP | S_IROTH);
+ 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. */
- if ( !IS_DOS_READONLY(dosmode) )
- result |= (S_IWUSR | S_IWGRP | S_IWOTH);
+ if (!lp_store_dos_attributes(SNUM(conn)) && IS_DOS_READONLY(dosmode)) {
+ result &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+ }
if (fname && lp_inherit_perms(SNUM(conn))) {
char *dname;
@@ -160,21 +161,129 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf)
}
/****************************************************************************
+ Get DOS attributes from an EA.
+****************************************************************************/
+
+static BOOL get_ea_dos_attribute(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf, uint32 *pattr)
+{
+ ssize_t sizeret;
+ fstring attrstr;
+ unsigned int dosattr;
+
+ if (!lp_store_dos_attributes(SNUM(conn))) {
+ return False;
+ }
+
+ *pattr = 0;
+
+ sizeret = SMB_VFS_GETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, sizeof(attrstr));
+ if (sizeret == -1) {
+#if defined(ENOTSUP) && defined(ENOATTR)
+ if ((errno != ENOTSUP) && (errno != ENOATTR) && (errno != EACCES)) {
+ DEBUG(1,("get_ea_dos_attributes: Cannot get attribute from EA on file %s: Error = %s\n",
+ path, strerror(errno) ));
+ }
+#endif
+ return False;
+ }
+ /* Null terminate string. */
+ attrstr[sizeret] = 0;
+ DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n", path, attrstr));
+
+ if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
+ sscanf(attrstr, "%x", &dosattr) != 1) {
+ DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on file %s - %s\n", path, attrstr));
+ return False;
+ }
+
+ if (S_ISDIR(sbuf->st_mode)) {
+ dosattr |= aDIR;
+ }
+ *pattr = (uint32)(dosattr & SAMBA_ATTRIBUTES_MASK);
+
+ DEBUG(8,("get_ea_dos_attribute returning (0x%x)", dosattr));
+
+ if (dosattr & aHIDDEN) DEBUG(8, ("h"));
+ if (dosattr & aRONLY ) DEBUG(8, ("r"));
+ if (dosattr & aSYSTEM) DEBUG(8, ("s"));
+ if (dosattr & aDIR ) DEBUG(8, ("d"));
+ if (dosattr & aARCH ) DEBUG(8, ("a"));
+
+ DEBUG(8,("\n"));
+
+ return True;
+}
+
+/****************************************************************************
+ Set DOS attributes in an EA.
+****************************************************************************/
+
+static BOOL set_ea_dos_attribute(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf, uint32 dosmode)
+{
+ fstring attrstr;
+ files_struct *fsp = NULL;
+ BOOL ret = False;
+
+ snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == -1) {
+ if((errno != EPERM) && (errno != EACCES)) {
+ return False;
+ }
+
+ /* We want DOS semantics, ie allow non owner with write permission to change the
+ bits on a file. Just like file_utime below.
+ */
+
+ /* Check if we have write access. */
+ if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
+ return False;
+
+ /*
+ * We need to open the file with write access whilst
+ * still in our current user context. This ensures we
+ * are not violating security in doing the setxattr.
+ */
+
+ fsp = open_file_fchmod(conn,path,sbuf);
+ if (!fsp)
+ return ret;
+ become_root();
+ if (SMB_VFS_SETXATTR(conn, path, SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr), 0) == 0) {
+ ret = True;
+ }
+ unbecome_root();
+ close_file_fchmod(fsp);
+ return ret;
+ }
+ DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr, path));
+ return True;
+}
+
+/****************************************************************************
Change a unix mode to a dos mode.
****************************************************************************/
-uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
+uint32 dos_mode(connection_struct *conn, const char *path,SMB_STRUCT_STAT *sbuf)
{
- int result = 0;
+ uint32 result = 0;
DEBUG(8,("dos_mode: %s\n", path));
+ if (!VALID_STAT(*sbuf)) {
+ return 0;
+ }
+
+ /* Get the DOS attributes from an EA by preference. */
+ if (get_ea_dos_attribute(conn, path, sbuf, &result)) {
+ return result;
+ }
+
result = dos_mode_from_sbuf(conn, sbuf);
/* Now do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(conn))) {
- char *p = strrchr_m(path,'/');
+ const char *p = strrchr_m(path,'/');
if (p)
p++;
else
@@ -207,7 +316,7 @@ uint32 dos_mode(connection_struct *conn,char *path,SMB_STRUCT_STAT *sbuf)
chmod a file - but preserve some bits.
********************************************************************/
-int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_STAT *st)
+int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, SMB_STRUCT_STAT *st)
{
SMB_STRUCT_STAT st1;
int mask=0;
@@ -215,6 +324,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
mode_t unixmode;
int ret = -1;
+ DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n", dosmode, fname));
if (!st) {
st = &st1;
if (SMB_VFS_STAT(conn,fname,st))
@@ -231,6 +341,11 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST
if (dos_mode(conn,fname,st) == dosmode)
return(0);
+ /* Store the DOS attributes in an EA by preference. */
+ if (set_ea_dos_attribute(conn, fname, st, dosmode)) {
+ return 0;
+ }
+
unixmode = unix_mode(conn,dosmode,fname);
/* preserve the s bits */
diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c
index 86d78e039a..5ccb548ba5 100644
--- a/source3/smbd/fake_file.c
+++ b/source3/smbd/fake_file.c
@@ -26,7 +26,7 @@
files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 desired_access,
- int share_mode,int ofun, mode_t mode,int oplock_request,
+ int share_mode,int ofun, uint32 new_dos_attr, int oplock_request,
int *Access,int *action)
{
extern struct current_user current_user;
@@ -35,7 +35,7 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
if (fake_file_type == 0) {
return open_file_shared1(conn,fname,psbuf,desired_access,
- share_mode,ofun,mode,
+ share_mode,ofun,new_dos_attr,
oplock_request,Access,action);
}
@@ -51,8 +51,8 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect
if(!fsp)
return NULL;
- DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
- fname, fsp->fnum, share_mode, ofun, (int)mode, oplock_request ));
+ DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, oplock request = %d\n",
+ fname, fsp->fnum, share_mode, ofun, oplock_request ));
if (!check_name(fname,conn)) {
file_free(fsp);
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 3462a3b9fa..c2fb6e3456 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -176,8 +176,9 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n)
if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) {
int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
fsp->size = (SMB_BIG_UINT)st.st_size;
- if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode))
- file_chmod(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
+ if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) {
+ file_set_dosmode(fsp->conn,fsp->fsp_name,dosmode | aARCH,&st);
+ }
/*
* If this is the first write and we have an exclusive oplock then setup
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 21b6db8b46..c9cc44627d 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -586,11 +586,9 @@ int reply_ntcreate_and_X(connection_struct *conn,
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
@@ -766,8 +764,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -781,7 +777,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
restore_case_semantics(file_attributes);
@@ -811,14 +807,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
fsp = open_file_shared1(conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes,oplock_request,
&rmode,&smb_action);
} else {
/* to open a fake_file --metze */
fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun,file_attributes, oplock_request,
&rmode,&smb_action);
}
@@ -857,7 +853,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
@@ -1134,7 +1130,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
char *data = *ppdata;
/* Breakout the oplock request bits so we can set the reply bits separately. */
int oplock_request = 0;
- mode_t unixmode;
int fmode=0,rmode=0;
SMB_OFF_T file_len = 0;
SMB_STRUCT_STAT sbuf;
@@ -1154,7 +1149,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
- int smb_attr;
time_t c_time;
NTSTATUS status;
@@ -1192,7 +1186,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
create_options = IVAL(params,32);
sd_len = IVAL(params,36);
root_dir_fid = (uint16)IVAL(params,4);
- smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
if (create_options & FILE_OPEN_BY_FILE_ID) {
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
@@ -1297,8 +1290,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -1318,7 +1309,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* CreateDirectory() call.
*/
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
@@ -1332,7 +1323,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
*/
fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
- smb_open_mode,smb_ofun,unixmode,
+ smb_open_mode,smb_ofun,file_attributes,
oplock_request,&rmode,&smb_action);
if (!fsp) {
@@ -1350,7 +1341,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
oplock_request = 0;
- fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
+ fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
restore_case_semantics(file_attributes);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 084ae9a1bf..8ab5dab6ac 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -741,21 +741,10 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
}
-static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode,
- mode_t new_mode, mode_t *returned_mode)
+static BOOL open_match_attributes(connection_struct *conn, const char *path, uint32 old_dos_mode, uint32 new_dos_mode,
+ mode_t existing_mode, mode_t new_mode, mode_t *returned_mode)
{
- uint32 old_dos_mode, new_dos_mode;
uint32 noarch_old_dos_mode, noarch_new_dos_mode;
- SMB_STRUCT_STAT sbuf;
-
- ZERO_STRUCT(sbuf);
-
- sbuf.st_mode = existing_mode;
- old_dos_mode = dos_mode(conn, path, &sbuf);
-
- sbuf.st_mode = new_mode;
- /* The new mode conversion shouldn't look at pathname. */
- new_dos_mode = dos_mode_from_sbuf(conn, &sbuf);
noarch_old_dos_mode = (old_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
noarch_new_dos_mode = (new_dos_mode & ~FILE_ATTRIBUTE_ARCHIVE);
@@ -771,11 +760,11 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex
old_dos_mode, (unsigned int)existing_mode, new_dos_mode, (unsigned int)*returned_mode ));
/* If we're mapping SYSTEM and HIDDEN ensure they match. */
- if (lp_map_system(SNUM(conn))) {
+ if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) && !(new_dos_mode & FILE_ATTRIBUTE_SYSTEM))
return False;
}
- if (lp_map_hidden(SNUM(conn))) {
+ if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) && !(new_dos_mode & FILE_ATTRIBUTE_HIDDEN))
return False;
}
@@ -787,10 +776,10 @@ static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t ex
****************************************************************************/
files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
- int share_mode,int ofun, mode_t mode,int oplock_request,
+ int share_mode,int ofun, uint32 new_dos_mode, int oplock_request,
int *Access,int *action)
{
- return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, mode,
+ return open_file_shared1(conn, fname, psbuf, 0, share_mode, ofun, new_dos_mode,
oplock_request, Access, action);
}
@@ -800,8 +789,9 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_STAT *psbuf,
uint32 desired_access,
- int share_mode,int ofun, mode_t mode,int oplock_request,
- int *Access,int *action)
+ int share_mode,int ofun, uint32 new_dos_mode,
+ int oplock_request,
+ int *Access,int *paction)
{
int flags=0;
int flags2=0;
@@ -820,6 +810,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
int open_mode=0;
uint16 port = 0;
mode_t new_mode = (mode_t)0;
+ int action;
+ uint32 existing_dos_mode = 0;
+ /* We add aARCH to this as this mode is only used if the file is created new. */
+ mode_t mode = unix_mode(conn,new_dos_mode | aARCH,fname);
if (conn->printer) {
/* printers are handled completely differently. Most of the passed parameters are
@@ -827,7 +821,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
if (Access)
*Access = DOS_OPEN_WRONLY;
if (action)
- *action = FILE_WAS_CREATED;
+ *paction = FILE_WAS_CREATED;
return print_fsp_open(conn, fname);
}
@@ -835,14 +829,19 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
if(!fsp)
return NULL;
- DEBUG(10,("open_file_shared: fname = %s, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
- fname, share_mode, ofun, (int)mode, oplock_request ));
+ DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n",
+ fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request ));
if (!check_name(fname,conn)) {
file_free(fsp);
return NULL;
}
+ new_dos_mode &= SAMBA_ATTRIBUTES_MASK;
+ if (file_existed) {
+ existing_dos_mode = dos_mode(conn, fname, psbuf);
+ }
+
/* ignore any oplock requests if oplocks are disabled */
if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) {
oplock_request = 0;
@@ -883,9 +882,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
/* We only care about matching attributes on file exists and truncate. */
if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) {
- if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) {
- DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n",
- fname, (int)psbuf->st_mode, (int)mode ));
+ if (!open_match_attributes(conn, fname, existing_dos_mode, new_dos_mode,
+ psbuf->st_mode, mode, &new_mode)) {
+ DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n",
+ fname, existing_dos_mode, new_dos_mode,
+ (int)psbuf->st_mode, (int)mode ));
file_free(fsp);
errno = EACCES;
return NULL;
@@ -929,7 +930,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
#endif /* O_SYNC */
if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,psbuf)))) {
+ (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_mode))) {
if (!fcbopen) {
DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n",
fname, !CAN_WRITE(conn) ? "share" : "file" ));
@@ -1120,16 +1121,19 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode ));
- if (Access)
+ if (Access) {
(*Access) = open_mode;
+ }
- if (action) {
- if (file_existed && !(flags2 & O_TRUNC))
- *action = FILE_WAS_OPENED;
- if (!file_existed)
- *action = FILE_WAS_CREATED;
- if (file_existed && (flags2 & O_TRUNC))
- *action = FILE_WAS_OVERWRITTEN;
+ if (file_existed && !(flags2 & O_TRUNC))
+ action = FILE_WAS_OPENED;
+ if (file_existed && (flags2 & O_TRUNC))
+ action = FILE_WAS_OVERWRITTEN;
+ if (!file_existed)
+ action = FILE_WAS_CREATED;
+
+ if (paction) {
+ *paction = action;
}
/*
@@ -1164,6 +1168,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n",
}
}
+ if (action == FILE_WAS_OVERWRITTEN || action == FILE_WAS_CREATED) {
+ /* Files should be initially set as archive */
+ if (lp_map_archive(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
+ file_set_dosmode(conn, fname, new_dos_mode | aARCH, NULL);
+ }
+ }
+
/*
* Take care of inherited ACLs on created files - if default ACL not
* selected.
@@ -1257,7 +1268,7 @@ int close_file_fchmod(files_struct *fsp)
****************************************************************************/
files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf,
- uint32 desired_access, int share_mode, int smb_ofun, mode_t unixmode, int *action)
+ uint32 desired_access, int share_mode, int smb_ofun, int *action)
{
extern struct current_user current_user;
BOOL got_stat = False;
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index ee370437ec..620e123e14 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -3181,7 +3181,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
the mask bits, not the real group bits, for a file with an ACL.
****************************************************************************/
-int get_acl_group_bits( connection_struct *conn, char *fname, mode_t *mode )
+int get_acl_group_bits( connection_struct *conn, const char *fname, mode_t *mode )
{
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index f5c4f25e40..fde4ee627f 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -678,8 +678,9 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
else
mode &= ~aDIR;
- if (check_name(fname,conn))
- ok = (file_chmod(conn,fname,mode,NULL) == 0);
+ if (check_name(fname,conn)) {
+ ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
+ }
} else {
ok = True;
}
@@ -1008,12 +1009,12 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int share_mode;
SMB_OFF_T size = 0;
time_t mtime=0;
- mode_t unixmode;
int rmode=0;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+ uint16 dos_attr = SVAL(inbuf,smb_vwv1);
NTSTATUS status;
START_PROFILE(SMBopen);
@@ -1029,10 +1030,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,aARCH,fname);
-
fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- unixmode, oplock_request,&rmode,NULL);
+ (uint32)dos_attr, oplock_request,&rmode,NULL);
if (!fsp) {
END_PROFILE(SMBopen);
@@ -1089,7 +1088,6 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
- mode_t unixmode;
SMB_OFF_T size=0;
int fmode=0,mtime=0,rmode=0;
SMB_STRUCT_STAT sbuf;
@@ -1121,9 +1119,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,smb_attr | aARCH, fname);
-
- fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
+ fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
oplock_request, &rmode,&smb_action);
if (!fsp) {
@@ -1215,7 +1211,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
int com;
int outsize = 0;
int createmode;
- mode_t unixmode;
int ofun = 0;
BOOL bad_path = False;
files_struct *fsp;
@@ -1240,8 +1235,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
if (createmode & aVOLID)
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
- unixmode = unix_mode(conn,createmode,fname);
-
if(com == SMBmknew) {
/* We should fail if file exists. */
ofun = FILE_CREATE_IF_NOT_EXIST;
@@ -1252,7 +1245,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* Open file in dos compatibility share mode. */
fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- ofun, unixmode, oplock_request, NULL, NULL);
+ ofun, (uint32)createmode, oplock_request, NULL, NULL);
if (!fsp) {
END_PROFILE(SMBcreate);
@@ -1269,7 +1262,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "new file %s\n", fname ) );
- DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
+ DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
END_PROFILE(SMBcreate);
return(outsize);
@@ -1283,8 +1276,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
{
pstring fname;
int outsize = 0;
- int createmode;
- mode_t unixmode;
+ int createattr;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
@@ -1295,7 +1287,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBctemp);
- createmode = SVAL(inbuf,smb_vwv0);
+ createattr = SVAL(inbuf,smb_vwv0);
srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
@@ -1307,8 +1299,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
unix_convert(fname,conn,0,&bad_path,&sbuf);
- unixmode = unix_mode(conn,createmode,fname);
-
tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
END_PROFILE(SMBctemp);
@@ -1322,7 +1312,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
fsp = open_file_shared(conn,fname,&sbuf,
SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
- unixmode, oplock_request, NULL, NULL);
+ (uint32)createattr, oplock_request, NULL, NULL);
/* close fd from smb_mkstemp() */
close(tmpfd);
@@ -1356,8 +1346,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
DEBUG( 2, ( "created temp file %s\n", fname ) );
- DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
- fname, fsp->fd, createmode, (int)unixmode ) );
+ DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
+ fname, fsp->fd, sbuf.st_mode ) );
END_PROFILE(SMBctemp);
return(outsize);
@@ -1384,7 +1374,7 @@ static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT
unix_ERR_code = 0;
fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
@@ -1449,7 +1439,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOO
unix_ERR_code = 0;
fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
if (!fsp) {
NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
@@ -3949,7 +3939,8 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
pstring dest;
-
+ uint32 dosattrs;
+
*err_ret = 0;
pstrcpy(dest,dest1);
@@ -3967,7 +3958,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
return(False);
fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
+ (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
if (!fsp1)
return(False);
@@ -3975,11 +3966,12 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
if (!target_is_directory && count)
ofun = FILE_EXISTS_OPEN;
+ dosattrs = dos_mode(conn, src, &src_sbuf);
if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
ZERO_STRUCTP(&sbuf2);
fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
- ofun,src_sbuf.st_mode,0,&Access,&action);
+ ofun,dosattrs,0,&Access,&action);
if (!fsp2) {
close_file(fsp1,False);
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index b1807705a0..a88722edde 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -55,6 +55,7 @@ SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
static const char *prohibited_ea_names[] = {
SAMBA_POSIX_INHERITANCE_EA_NAME,
+ SAMBA_XATTR_DOS_ATTRIB,
NULL
};
@@ -538,7 +539,6 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
int32 open_size;
char *pname;
pstring fname;
- mode_t unixmode;
SMB_OFF_T size=0;
int fmode=0,mtime=0,rmode;
SMB_INO_T inode = 0;
@@ -586,9 +586,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
- unixmode = unix_mode(conn,open_attr | aARCH, fname);
-
- fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,unixmode,
+ fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
oplock_request, &rmode,&smb_action);
if (!fsp) {
@@ -3133,7 +3131,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL,
+ 0, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));
@@ -3528,8 +3527,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
- if(file_chmod(conn, fname, dosmode, NULL)) {
- DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
+ if(file_set_dosmode(conn, fname, dosmode, NULL)) {
+ DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
}
@@ -3559,7 +3558,8 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
new_fsp = open_file_shared(conn, fname, &sbuf,
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- 0, 0, &access_mode, &action);
+ FILE_ATTRIBUTE_NORMAL,
+ 0, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));