1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

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 commit is contained in:
Jeremy Allison 0001-01-01 00:00:00 +00:00
parent ae6840320f
commit ed653cd468
13 changed files with 227 additions and 110 deletions

View File

@ -1668,4 +1668,7 @@ struct ea_struct {
/* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */
#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI"
/* EA to use for DOS attributes */
#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
#endif /* _SMB_H */

View File

@ -379,6 +379,7 @@ typedef struct
BOOL bMap_system;
BOOL bMap_hidden;
BOOL bMap_archive;
BOOL bStoreDosAttributes;
BOOL bLocking;
BOOL bStrictLocking;
BOOL bPosixLocking;
@ -501,6 +502,7 @@ static service sDefault = {
False, /* bMap_system */
False, /* bMap_hidden */
True, /* bMap_archive */
False, /* bStoreDosAttributes */
True, /* bLocking */
True, /* bStrictLocking */
True, /* bPosixLocking */
@ -994,6 +996,7 @@ static struct parm_struct parm_table[] = {
{"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED },
{"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED},
{"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL},
{N_("Domain Options"), P_SEP, P_SEPARATOR},
@ -1844,6 +1847,7 @@ FN_LOCAL_BOOL(lp_guest_only, bGuest_only)
FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
FN_LOCAL_BOOL(lp_locking, bLocking)
FN_LOCAL_BOOL(lp_strict_locking, bStrictLocking)
FN_LOCAL_BOOL(lp_posix_locking, bPosixLocking)

View File

@ -992,7 +992,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
fsp = open_file_shared(conn, filepath, &stat_buf,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
0, 0, &access_mode, &action);
FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Old file not found, so by definition new file is in fact newer */
DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
@ -1021,7 +1021,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr
fsp = open_file_shared(conn, filepath, &stat_buf,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
0, 0, &access_mode, &action);
FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* New file not found, this shouldn't occur if the caller did its job */
DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
@ -1137,7 +1137,7 @@ static uint32 get_correct_cversion(const char *architecture, fstring driverpath_
fsp = open_file_shared(conn, driverpath, &st,
SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
0, 0, &access_mode, &action);
FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
driverpath, errno));

View File

@ -1887,13 +1887,13 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC
unistr2_to_ascii(filename, &q_u->uni_file_name, sizeof(filename));
unix_convert(filename, conn, NULL, &bad_path, &st);
fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDONLY),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Perhaps it is a directory */
if (errno == EISDIR)
fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
if (!fsp) {
DEBUG(3,("_srv_net_file_query_secdesc: Unable to open file %s\n", filename));
@ -1991,13 +1991,13 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_
unix_convert(filename, conn, NULL, &bad_path, &st);
fsp = open_file_shared(conn, filename, &st, SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &action);
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &action);
if (!fsp) {
/* Perhaps it is a directory */
if (errno == EISDIR)
fsp = open_directory(conn, filename, &st,FILE_READ_ATTRIBUTES,0,
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, &action);
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), &action);
if (!fsp) {
DEBUG(3,("_srv_net_file_set_secdesc: Unable to open file %s\n", filename));

View File

@ -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;

View File

@ -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;
@ -159,22 +160,130 @@ uint32 dos_mode_from_sbuf(connection_struct *conn, SMB_STRUCT_STAT *sbuf)
return result;
}
/****************************************************************************
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 */

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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));