1998-08-17 11:40:06 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-08-17 11:40:06 +04:00
dos mode handling functions
Copyright ( C ) Andrew Tridgell 1992 - 1998
2006-03-23 02:49:09 +03:00
Copyright ( C ) James Peach 2006
2009-05-24 23:46:53 +04:00
1998-08-17 11:40:06 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-08-17 11:40:06 +04:00
( at your option ) any later version .
2009-05-24 23:46:53 +04:00
1998-08-17 11:40:06 +04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2009-05-24 23:46:53 +04:00
1998-08-17 11:40:06 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-08-17 11:40:06 +04:00
*/
# include "includes.h"
2005-06-10 04:31:59 +04:00
static int set_sparse_flag ( const SMB_STRUCT_STAT * const sbuf )
{
# if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2009-05-14 17:34:42 +04:00
if ( sbuf - > st_ex_size > sbuf - > st_ex_blocks * ( SMB_OFF_T ) STAT_ST_BLOCKSIZE ) {
2005-06-10 04:31:59 +04:00
return FILE_ATTRIBUTE_SPARSE ;
}
# endif
return 0 ;
}
2008-11-06 00:40:03 +03:00
static int set_link_read_only_flag ( const SMB_STRUCT_STAT * const sbuf )
{
# ifdef S_ISLNK
# if LINKS_READ_ONLY
if ( S_ISLNK ( sbuf - > st_mode ) & & S_ISDIR ( sbuf - > st_mode ) )
return aRONLY ;
# endif
# endif
return 0 ;
}
1998-08-17 11:40:06 +04:00
/****************************************************************************
2004-04-01 02:46:15 +04:00
Change a dos mode to a unix mode .
Base permission for files :
2006-12-27 13:57:59 +03:00
if creating file and inheriting ( i . e . parent_dir ! = NULL )
2000-01-14 04:41:04 +03:00
apply read / write bits from parent directory .
else
everybody gets read bit set
1998-08-17 11:40:06 +04:00
dos readonly is represented in unix by removing everyone ' s write bit
dos archive is represented in unix by the user ' s execute bit
dos system is represented in unix by the group ' s execute bit
dos hidden is represented in unix by the other ' s execute bit
2000-01-14 04:41:04 +03:00
if ! inheriting {
Then apply create mask ,
then add force bits .
}
2004-04-01 02:46:15 +04:00
Base permission for directories :
1998-08-17 11:40:06 +04:00
dos directory is represented in unix by unix ' s dir bit and the exec bit
2000-01-14 04:41:04 +03:00
if ! inheriting {
Then apply create mask ,
then add force bits .
}
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-04-01 02:46:15 +04:00
2009-07-08 06:20:22 +04:00
mode_t unix_mode ( connection_struct * conn , int dosmode ,
const struct smb_filename * smb_fname ,
2006-12-27 13:57:59 +03:00
const char * inherit_from_dir )
1998-08-17 11:40:06 +04:00
{
2004-04-02 22:46:19 +04:00
mode_t result = ( S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH ) ;
2006-12-27 13:57:59 +03:00
mode_t dir_mode = 0 ; /* Mode of the inherit_from directory if
* inheriting . */
2004-04-01 02:46:15 +04:00
2004-04-02 22:46:19 +04:00
if ( ! lp_store_dos_attributes ( SNUM ( conn ) ) & & IS_DOS_READONLY ( dosmode ) ) {
result & = ~ ( S_IWUSR | S_IWGRP | S_IWOTH ) ;
}
2004-04-01 02:46:15 +04:00
2009-07-08 06:20:22 +04:00
if ( ( inherit_from_dir ! = NULL ) & & lp_inherit_perms ( SNUM ( conn ) ) ) {
struct smb_filename * smb_fname_parent = NULL ;
NTSTATUS status ;
2004-04-01 02:46:15 +04:00
2009-07-08 06:20:22 +04:00
DEBUG ( 2 , ( " unix_mode(%s) inheriting from %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
2006-12-27 13:57:59 +03:00
inherit_from_dir ) ) ;
2009-07-08 06:20:22 +04:00
status = create_synthetic_smb_fname ( talloc_tos ( ) ,
inherit_from_dir , NULL ,
NULL , & smb_fname_parent ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " unix_mode(%s) failed, [dir %s]: %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
inherit_from_dir , nt_errstr ( status ) ) ) ;
return ( 0 ) ;
}
if ( SMB_VFS_STAT ( conn , smb_fname_parent ) ! = 0 ) {
DEBUG ( 4 , ( " unix_mode(%s) failed, [dir %s]: %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
2006-12-27 13:57:59 +03:00
inherit_from_dir , strerror ( errno ) ) ) ;
2009-07-08 06:20:22 +04:00
TALLOC_FREE ( smb_fname_parent ) ;
2004-04-01 02:46:15 +04:00
return ( 0 ) ; /* *** shouldn't happen! *** */
}
/* Save for later - but explicitly remove setuid bit for safety. */
2009-07-08 06:20:22 +04:00
dir_mode = smb_fname_parent - > st . st_ex_mode & ~ S_ISUID ;
DEBUG ( 2 , ( " unix_mode(%s) inherit mode %o \n " ,
smb_fname_str_dbg ( smb_fname ) , ( int ) dir_mode ) ) ;
2004-04-01 02:46:15 +04:00
/* Clear "result" */
result = 0 ;
2009-07-08 06:20:22 +04:00
TALLOC_FREE ( smb_fname_parent ) ;
2004-04-01 02:46:15 +04:00
}
if ( IS_DOS_DIR ( dosmode ) ) {
/* We never make directories read only for the owner as under DOS a user
can always create a file in a read - only directory . */
result | = ( S_IFDIR | S_IWUSR ) ;
if ( dir_mode ) {
/* Inherit mode of parent directory. */
result | = dir_mode ;
} else {
/* Provisionally add all 'x' bits */
result | = ( S_IXUSR | S_IXGRP | S_IXOTH ) ;
/* Apply directory mask */
result & = lp_dir_mask ( SNUM ( conn ) ) ;
/* Add in force bits */
result | = lp_force_dir_mode ( SNUM ( conn ) ) ;
}
} else {
if ( lp_map_archive ( SNUM ( conn ) ) & & IS_DOS_ARCHIVE ( dosmode ) )
result | = S_IXUSR ;
if ( lp_map_system ( SNUM ( conn ) ) & & IS_DOS_SYSTEM ( dosmode ) )
result | = S_IXGRP ;
2009-05-24 23:46:53 +04:00
2004-04-01 02:46:15 +04:00
if ( lp_map_hidden ( SNUM ( conn ) ) & & IS_DOS_HIDDEN ( dosmode ) )
result | = S_IXOTH ;
if ( dir_mode ) {
/* Inherit 666 component of parent directory mode */
result | = dir_mode & ( S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH ) ;
} else {
/* Apply mode mask */
result & = lp_create_mask ( SNUM ( conn ) ) ;
/* Add in force bits */
result | = lp_force_create_mode ( SNUM ( conn ) ) ;
}
}
2009-07-08 06:20:22 +04:00
DEBUG ( 3 , ( " unix_mode(%s) returning 0%o \n " , smb_fname_str_dbg ( smb_fname ) ,
( int ) result ) ) ;
2004-04-01 02:46:15 +04:00
return ( result ) ;
1998-08-17 11:40:06 +04:00
}
/****************************************************************************
2004-04-01 02:46:15 +04:00
Change a unix mode to a dos mode .
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-20 02:46:48 +03:00
2009-07-08 23:24:03 +04:00
static uint32 dos_mode_from_sbuf ( connection_struct * conn ,
const struct smb_filename * smb_fname )
1998-08-17 11:40:06 +04:00
{
2002-08-17 19:27:10 +04:00
int result = 0 ;
2005-10-14 05:09:37 +04:00
enum mapreadonly_options ro_opts = ( enum mapreadonly_options ) lp_map_readonly ( SNUM ( conn ) ) ;
1998-08-17 11:40:06 +04:00
2005-10-14 05:09:37 +04:00
if ( ro_opts = = MAP_READONLY_YES ) {
/* Original Samba method - map inverse of user "w" bit. */
2009-07-08 23:24:03 +04:00
if ( ( smb_fname - > st . st_ex_mode & S_IWUSR ) = = 0 ) {
2005-10-14 05:09:37 +04:00
result | = aRONLY ;
}
} else if ( ro_opts = = MAP_READONLY_PERMISSIONS ) {
2009-07-08 23:24:03 +04:00
/* Check actual permissions for read-only. */
if ( ! can_write_to_file ( conn , smb_fname ) ) {
result | = aRONLY ;
2005-05-19 03:37:35 +04:00
}
2005-10-14 05:09:37 +04:00
} /* Else never set the readonly bit. */
2005-05-19 03:37:35 +04:00
2009-07-08 23:24:03 +04:00
if ( MAP_ARCHIVE ( conn ) & & ( ( smb_fname - > st . st_ex_mode & S_IXUSR ) ! = 0 ) )
2002-08-17 19:27:10 +04:00
result | = aARCH ;
1998-08-17 11:40:06 +04:00
2009-07-08 23:24:03 +04:00
if ( MAP_SYSTEM ( conn ) & & ( ( smb_fname - > st . st_ex_mode & S_IXGRP ) ! = 0 ) )
2002-08-17 19:27:10 +04:00
result | = aSYSTEM ;
2009-05-24 23:46:53 +04:00
2009-07-08 23:24:03 +04:00
if ( MAP_HIDDEN ( conn ) & & ( ( smb_fname - > st . st_ex_mode & S_IXOTH ) ! = 0 ) )
2002-08-17 19:27:10 +04:00
result | = aHIDDEN ;
2009-05-24 23:46:53 +04:00
2009-07-08 23:24:03 +04:00
if ( S_ISDIR ( smb_fname - > st . st_ex_mode ) )
2002-08-17 19:27:10 +04:00
result = aDIR | ( result & aRONLY ) ;
2009-07-08 23:24:03 +04:00
result | = set_sparse_flag ( & smb_fname - > st ) ;
result | = set_link_read_only_flag ( & smb_fname - > st ) ;
1998-08-17 11:40:06 +04:00
2004-03-20 02:46:48 +03:00
DEBUG ( 8 , ( " dos_mode_from_sbuf returning " ) ) ;
if ( result & aHIDDEN ) DEBUG ( 8 , ( " h " ) ) ;
if ( result & aRONLY ) DEBUG ( 8 , ( " r " ) ) ;
if ( result & aSYSTEM ) DEBUG ( 8 , ( " s " ) ) ;
if ( result & aDIR ) DEBUG ( 8 , ( " d " ) ) ;
if ( result & aARCH ) DEBUG ( 8 , ( " a " ) ) ;
2009-05-24 23:46:53 +04:00
2004-03-20 02:46:48 +03:00
DEBUG ( 8 , ( " \n " ) ) ;
return result ;
}
2004-04-02 22:46:19 +04:00
/****************************************************************************
Get DOS attributes from an EA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-08 23:24:03 +04:00
static bool get_ea_dos_attribute ( connection_struct * conn ,
const struct smb_filename * smb_fname ,
uint32 * pattr )
2004-04-02 22:46:19 +04:00
{
ssize_t sizeret ;
fstring attrstr ;
unsigned int dosattr ;
if ( ! lp_store_dos_attributes ( SNUM ( conn ) ) ) {
return False ;
}
2005-11-28 20:03:50 +03:00
/* Don't reset pattr to zero as we may already have filename-based attributes we
need to preserve . */
2004-04-02 22:46:19 +04:00
2009-07-08 23:24:03 +04:00
sizeret = SMB_VFS_GETXATTR ( conn , smb_fname - > base_name ,
SAMBA_XATTR_DOS_ATTRIB , attrstr ,
sizeof ( attrstr ) ) ;
2004-04-02 22:46:19 +04:00
if ( sizeret = = - 1 ) {
2009-01-08 01:57:20 +03:00
if ( errno = = ENOSYS
# if defined(ENOTSUP)
| | errno = = ENOTSUP ) {
# else
) {
# endif
2009-07-08 23:24:03 +04:00
DEBUG ( 1 , ( " get_ea_dos_attributes: Cannot get attribute "
" from EA on file %s: Error = %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ) ;
2004-06-02 00:43:32 +04:00
set_store_dos_attributes ( SNUM ( conn ) , False ) ;
2004-04-02 22:46:19 +04:00
}
return False ;
}
/* Null terminate string. */
attrstr [ sizeret ] = 0 ;
2009-07-08 23:24:03 +04:00
DEBUG ( 10 , ( " get_ea_dos_attribute: %s attrstr = %s \n " ,
smb_fname_str_dbg ( smb_fname ) , attrstr ) ) ;
2004-04-02 22:46:19 +04:00
if ( sizeret < 2 | | attrstr [ 0 ] ! = ' 0 ' | | attrstr [ 1 ] ! = ' x ' | |
sscanf ( attrstr , " %x " , & dosattr ) ! = 1 ) {
2009-07-08 23:24:03 +04:00
DEBUG ( 1 , ( " get_ea_dos_attributes: Badly formed DOSATTRIB on "
" file %s - %s \n " , smb_fname_str_dbg ( smb_fname ) ,
attrstr ) ) ;
2004-04-02 22:46:19 +04:00
return False ;
}
2009-07-08 23:24:03 +04:00
if ( S_ISDIR ( smb_fname - > st . st_ex_mode ) ) {
2004-04-02 22:46:19 +04:00
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 " ) ) ;
2009-05-24 23:46:53 +04:00
2004-04-02 22:46:19 +04:00
DEBUG ( 8 , ( " \n " ) ) ;
return True ;
}
/****************************************************************************
Set DOS attributes in an EA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-08 23:24:03 +04:00
static bool set_ea_dos_attribute ( connection_struct * conn ,
struct smb_filename * smb_fname ,
uint32 dosmode )
2004-04-02 22:46:19 +04:00
{
fstring attrstr ;
files_struct * fsp = NULL ;
2007-10-19 04:40:25 +04:00
bool ret = False ;
2004-04-02 22:46:19 +04:00
2004-06-02 00:43:32 +04:00
if ( ! lp_store_dos_attributes ( SNUM ( conn ) ) ) {
return False ;
}
2004-04-02 22:46:19 +04:00
snprintf ( attrstr , sizeof ( attrstr ) - 1 , " 0x%x " , dosmode & SAMBA_ATTRIBUTES_MASK ) ;
2009-07-08 23:24:03 +04:00
if ( SMB_VFS_SETXATTR ( conn , smb_fname - > base_name ,
SAMBA_XATTR_DOS_ATTRIB , attrstr , strlen ( attrstr ) ,
0 ) = = - 1 ) {
2004-04-02 22:46:19 +04:00
if ( ( errno ! = EPERM ) & & ( errno ! = EACCES ) ) {
2004-06-02 00:43:32 +04:00
if ( errno = = ENOSYS
# if defined(ENOTSUP)
| | errno = = ENOTSUP ) {
# else
) {
# endif
2009-07-08 23:24:03 +04:00
DEBUG ( 1 , ( " set_ea_dos_attributes: Cannot set "
" attribute EA on file %s: Error = %s \n " ,
smb_fname_str_dbg ( smb_fname ) ,
strerror ( errno ) ) ) ;
2004-06-02 00:43:32 +04:00
set_store_dos_attributes ( SNUM ( conn ) , False ) ;
}
2004-04-02 22:46:19 +04:00
return False ;
}
/* We want DOS semantics, ie allow non owner with write permission to change the
2007-03-06 02:40:03 +03:00
bits on a file . Just like file_ntimes below .
2004-04-02 22:46:19 +04:00
*/
/* 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 .
*/
2009-07-08 23:24:03 +04:00
if ( ! NT_STATUS_IS_OK ( open_file_fchmod ( NULL , conn , smb_fname ,
2008-10-09 17:38:53 +04:00
& fsp ) ) )
2004-04-02 22:46:19 +04:00
return ret ;
become_root ( ) ;
2009-07-08 23:24:03 +04:00
if ( SMB_VFS_SETXATTR ( conn , smb_fname - > base_name ,
SAMBA_XATTR_DOS_ATTRIB , attrstr ,
strlen ( attrstr ) , 0 ) = = 0 ) {
2004-04-02 22:46:19 +04:00
ret = True ;
}
unbecome_root ( ) ;
2008-10-09 18:27:49 +04:00
close_file_fchmod ( NULL , fsp ) ;
2004-04-02 22:46:19 +04:00
return ret ;
}
2009-07-08 23:24:03 +04:00
DEBUG ( 10 , ( " set_ea_dos_attribute: set EA %s on file %s \n " , attrstr ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2004-04-02 22:46:19 +04:00
return True ;
}
2006-07-04 01:07:46 +04:00
/****************************************************************************
Change a unix mode to a dos mode for an ms dfs link .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-08 23:24:03 +04:00
uint32 dos_mode_msdfs ( connection_struct * conn ,
const struct smb_filename * smb_fname )
2006-07-04 01:07:46 +04:00
{
uint32 result = 0 ;
2009-07-08 23:24:03 +04:00
DEBUG ( 8 , ( " dos_mode_msdfs: %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2006-07-04 01:07:46 +04:00
2009-07-08 23:24:03 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
2006-07-04 01:07:46 +04:00
return 0 ;
}
/* First do any modifications that depend on the path name. */
/* hide files with a name starting with a . */
if ( lp_hide_dot_files ( SNUM ( conn ) ) ) {
2009-07-08 23:24:03 +04:00
const char * p = strrchr_m ( smb_fname - > base_name , ' / ' ) ;
2006-07-04 01:07:46 +04:00
if ( p ) {
p + + ;
} else {
2009-07-08 23:24:03 +04:00
p = smb_fname - > base_name ;
2006-07-04 01:07:46 +04:00
}
2009-03-31 02:05:39 +04:00
/* Only . and .. are not hidden. */
if ( p [ 0 ] = = ' . ' & & ! ( ( p [ 1 ] = = ' \0 ' ) | |
( p [ 1 ] = = ' . ' & & p [ 2 ] = = ' \0 ' ) ) ) {
2006-07-04 01:07:46 +04:00
result | = aHIDDEN ;
}
}
2009-05-24 23:46:53 +04:00
2009-07-08 23:24:03 +04:00
result | = dos_mode_from_sbuf ( conn , smb_fname ) ;
2006-07-04 01:07:46 +04:00
/* Optimization : Only call is_hidden_path if it's not already
hidden . */
2009-07-08 23:24:03 +04:00
if ( ! ( result & aHIDDEN ) & &
IS_HIDDEN_PATH ( conn , smb_fname - > base_name ) ) {
2006-07-04 01:07:46 +04:00
result | = aHIDDEN ;
}
DEBUG ( 8 , ( " dos_mode_msdfs returning " ) ) ;
if ( result & aHIDDEN ) DEBUG ( 8 , ( " h " ) ) ;
if ( result & aRONLY ) DEBUG ( 8 , ( " r " ) ) ;
if ( result & aSYSTEM ) DEBUG ( 8 , ( " s " ) ) ;
if ( result & aDIR ) DEBUG ( 8 , ( " d " ) ) ;
if ( result & aARCH ) DEBUG ( 8 , ( " a " ) ) ;
if ( result & FILE_ATTRIBUTE_SPARSE ) DEBUG ( 8 , ( " [sparse] " ) ) ;
2009-05-24 23:46:53 +04:00
2006-07-04 01:07:46 +04:00
DEBUG ( 8 , ( " \n " ) ) ;
return ( result ) ;
}
2008-11-06 00:40:03 +03:00
# ifdef HAVE_STAT_DOS_FLAGS
/****************************************************************************
Convert dos attributes ( FILE_ATTRIBUTE_ * ) to dos stat flags ( UF_ * )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-30 03:28:19 +03:00
int dos_attributes_to_stat_dos_flags ( uint32_t dosmode )
2008-11-06 00:40:03 +03:00
{
uint32_t dos_stat_flags = 0 ;
if ( dosmode & aARCH )
dos_stat_flags | = UF_DOS_ARCHIVE ;
if ( dosmode & aHIDDEN )
dos_stat_flags | = UF_DOS_HIDDEN ;
if ( dosmode & aRONLY )
dos_stat_flags | = UF_DOS_RO ;
if ( dosmode & aSYSTEM )
dos_stat_flags | = UF_DOS_SYSTEM ;
if ( dosmode & FILE_ATTRIBUTE_NONINDEXED )
dos_stat_flags | = UF_DOS_NOINDEX ;
return dos_stat_flags ;
}
/****************************************************************************
2009-05-29 01:11:17 +04:00
Gets DOS attributes , accessed via st_ex_flags in the stat struct .
2008-11-06 00:40:03 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool get_stat_dos_flags ( connection_struct * conn ,
2009-07-08 23:24:03 +04:00
const struct smb_filename * smb_fname ,
2008-11-06 00:40:03 +03:00
uint32_t * dosmode )
{
2009-07-08 23:24:03 +04:00
SMB_ASSERT ( VALID_STAT ( smb_fname - > st ) ) ;
2008-11-06 00:40:03 +03:00
SMB_ASSERT ( dosmode ) ;
if ( ! lp_store_dos_attributes ( SNUM ( conn ) ) ) {
return false ;
}
2009-07-08 23:24:03 +04:00
DEBUG ( 5 , ( " Getting stat dos attributes for %s. \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2008-11-06 00:40:03 +03:00
2009-07-08 23:24:03 +04:00
if ( smb_fname - > st . st_ex_flags & UF_DOS_ARCHIVE )
2008-11-06 00:40:03 +03:00
* dosmode | = aARCH ;
2009-07-08 23:24:03 +04:00
if ( smb_fname - > st . st_ex_flags & UF_DOS_HIDDEN )
2008-11-06 00:40:03 +03:00
* dosmode | = aHIDDEN ;
2009-07-08 23:24:03 +04:00
if ( smb_fname - > st . st_ex_flags & UF_DOS_RO )
2008-11-06 00:40:03 +03:00
* dosmode | = aRONLY ;
2009-07-08 23:24:03 +04:00
if ( smb_fname - > st . st_ex_flags & UF_DOS_SYSTEM )
2008-11-06 00:40:03 +03:00
* dosmode | = aSYSTEM ;
2009-07-08 23:24:03 +04:00
if ( smb_fname - > st . st_ex_flags & UF_DOS_NOINDEX )
2008-11-06 00:40:03 +03:00
* dosmode | = FILE_ATTRIBUTE_NONINDEXED ;
2009-07-08 23:24:03 +04:00
if ( S_ISDIR ( smb_fname - > st . st_ex_mode ) )
2008-11-06 00:40:03 +03:00
* dosmode | = aDIR ;
2009-07-10 02:56:36 +04:00
* dosmode | = set_sparse_flag ( & smb_fname - > st ) ;
* dosmode | = set_link_read_only_flag ( & smb_fname - > st ) ;
2008-11-06 00:40:03 +03:00
return true ;
}
/****************************************************************************
2009-05-29 01:11:17 +04:00
Sets DOS attributes , stored in st_ex_flags of the inode .
2008-11-06 00:40:03 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool set_stat_dos_flags ( connection_struct * conn ,
2009-07-07 01:36:16 +04:00
const struct smb_filename * smb_fname ,
uint32_t dosmode ,
bool * attributes_changed )
2008-11-06 00:40:03 +03:00
{
uint32_t new_flags = 0 ;
int error = 0 ;
2009-07-07 01:36:16 +04:00
SMB_ASSERT ( VALID_STAT ( smb_fname - > st ) ) ;
2008-11-06 00:40:03 +03:00
SMB_ASSERT ( attributes_changed ) ;
* attributes_changed = false ;
if ( ! lp_store_dos_attributes ( SNUM ( conn ) ) ) {
return false ;
}
2009-07-07 01:36:16 +04:00
DEBUG ( 5 , ( " Setting stat dos attributes for %s. \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2008-11-06 00:40:03 +03:00
2009-07-07 01:36:16 +04:00
new_flags = ( smb_fname - > st . st_ex_flags & ~ UF_DOS_FLAGS ) |
2008-11-06 00:40:03 +03:00
dos_attributes_to_stat_dos_flags ( dosmode ) ;
/* Return early if no flags changed. */
2009-07-07 01:36:16 +04:00
if ( new_flags = = smb_fname - > st . st_ex_flags )
2008-11-06 00:40:03 +03:00
return true ;
DEBUG ( 5 , ( " Setting stat dos attributes=0x%x, prev=0x%x \n " , new_flags ,
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_flags ) ) ;
2008-11-06 00:40:03 +03:00
/* Set new flags with chflags. */
2009-07-07 01:36:16 +04:00
error = SMB_VFS_CHFLAGS ( conn , smb_fname - > base_name , new_flags ) ;
2008-11-06 00:40:03 +03:00
if ( error ) {
DEBUG ( 0 , ( " Failed setting new stat dos attributes (0x%x) on "
2009-07-07 01:36:16 +04:00
" file %s! errno=%d \n " , new_flags ,
smb_fname_str_dbg ( smb_fname ) , errno ) ) ;
2008-11-06 00:40:03 +03:00
return false ;
}
* attributes_changed = true ;
return true ;
}
# endif /* HAVE_STAT_DOS_FLAGS */
2004-03-20 02:46:48 +03:00
/****************************************************************************
2004-04-01 02:46:15 +04:00
Change a unix mode to a dos mode .
2004-03-20 02:46:48 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-04-01 02:46:15 +04:00
2009-07-08 23:24:03 +04:00
uint32 dos_mode ( connection_struct * conn , const struct smb_filename * smb_fname )
2004-03-20 02:46:48 +03:00
{
2009-07-08 23:24:03 +04:00
SMB_STRUCT_STAT sbuf ;
2004-04-02 22:46:19 +04:00
uint32 result = 0 ;
2008-11-06 00:40:03 +03:00
bool offline , used_stat_dos_flags = false ;
2004-03-20 02:46:48 +03:00
2009-07-08 23:24:03 +04:00
DEBUG ( 8 , ( " dos_mode: %s \n " , smb_fname_str_dbg ( smb_fname ) ) ) ;
2004-03-20 02:46:48 +03:00
2009-07-08 23:24:03 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
2004-04-02 22:46:19 +04:00
return 0 ;
}
2005-09-21 00:20:51 +04:00
/* First do any modifications that depend on the path name. */
2002-08-17 19:27:10 +04:00
/* hide files with a name starting with a . */
if ( lp_hide_dot_files ( SNUM ( conn ) ) ) {
2009-07-08 23:24:03 +04:00
const char * p = strrchr_m ( smb_fname - > base_name , ' / ' ) ;
2005-09-21 00:20:51 +04:00
if ( p ) {
2002-08-17 19:27:10 +04:00
p + + ;
2005-09-21 00:20:51 +04:00
} else {
2009-07-08 23:24:03 +04:00
p = smb_fname - > base_name ;
2005-09-21 00:20:51 +04:00
}
2009-03-31 02:05:39 +04:00
/* Only . and .. are not hidden. */
if ( p [ 0 ] = = ' . ' & & ! ( ( p [ 1 ] = = ' \0 ' ) | |
( p [ 1 ] = = ' . ' & & p [ 2 ] = = ' \0 ' ) ) ) {
2002-08-17 19:27:10 +04:00
result | = aHIDDEN ;
2005-09-21 00:20:51 +04:00
}
2002-08-17 19:27:10 +04:00
}
2009-05-24 23:46:53 +04:00
2008-11-06 00:40:03 +03:00
# ifdef HAVE_STAT_DOS_FLAGS
2009-07-08 23:24:03 +04:00
used_stat_dos_flags = get_stat_dos_flags ( conn , smb_fname , & result ) ;
2008-11-06 00:40:03 +03:00
# endif
if ( ! used_stat_dos_flags ) {
/* Get the DOS attributes from an EA by preference. */
2009-07-08 23:24:03 +04:00
if ( get_ea_dos_attribute ( conn , smb_fname , & result ) ) {
result | = set_sparse_flag ( & smb_fname - > st ) ;
2008-11-06 00:40:03 +03:00
} else {
2009-07-08 23:24:03 +04:00
result | = dos_mode_from_sbuf ( conn , smb_fname ) ;
2008-11-06 00:40:03 +03:00
}
2005-09-21 00:20:51 +04:00
}
2009-07-08 23:24:03 +04:00
sbuf = smb_fname - > st ;
offline = SMB_VFS_IS_OFFLINE ( conn , smb_fname - > base_name , & sbuf ) ;
2009-06-19 02:07:14 +04:00
if ( S_ISREG ( sbuf . st_ex_mode ) & & offline ) {
2008-01-16 12:17:03 +03:00
result | = FILE_ATTRIBUTE_OFFLINE ;
2006-03-23 02:49:09 +03:00
}
2002-08-17 19:27:10 +04:00
/* Optimization : Only call is_hidden_path if it's not already
hidden . */
2009-07-08 23:24:03 +04:00
if ( ! ( result & aHIDDEN ) & &
IS_HIDDEN_PATH ( conn , smb_fname - > base_name ) ) {
2002-08-17 19:27:10 +04:00
result | = aHIDDEN ;
}
DEBUG ( 8 , ( " dos_mode returning " ) ) ;
if ( result & aHIDDEN ) DEBUG ( 8 , ( " h " ) ) ;
if ( result & aRONLY ) DEBUG ( 8 , ( " r " ) ) ;
if ( result & aSYSTEM ) DEBUG ( 8 , ( " s " ) ) ;
if ( result & aDIR ) DEBUG ( 8 , ( " d " ) ) ;
if ( result & aARCH ) DEBUG ( 8 , ( " a " ) ) ;
2005-11-14 09:29:48 +03:00
if ( result & FILE_ATTRIBUTE_SPARSE ) DEBUG ( 8 , ( " [sparse] " ) ) ;
2009-05-24 23:46:53 +04:00
2002-08-17 19:27:10 +04:00
DEBUG ( 8 , ( " \n " ) ) ;
return ( result ) ;
1998-08-17 11:40:06 +04:00
}
/*******************************************************************
2004-04-01 02:46:15 +04:00
chmod a file - but preserve some bits .
1998-08-17 11:40:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-11-26 02:25:42 +03:00
2009-07-07 01:36:16 +04:00
int file_set_dosmode ( connection_struct * conn , struct smb_filename * smb_fname ,
uint32 dosmode , const char * parent_dir , bool newfile )
1998-08-17 11:40:06 +04:00
{
2001-01-09 23:34:37 +03:00
int mask = 0 ;
mode_t tmp ;
mode_t unixmode ;
2008-01-16 12:17:03 +03:00
int ret = - 1 , lret = - 1 ;
2008-02-06 09:09:23 +03:00
uint32_t old_mode ;
2001-01-09 23:34:37 +03:00
2005-11-14 09:29:48 +03:00
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
2008-02-06 21:31:22 +03:00
dosmode & = ( SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE ) ;
2005-11-14 09:29:48 +03:00
2009-07-07 01:36:16 +04:00
DEBUG ( 10 , ( " file_set_dosmode: setting dos mode 0x%x on file %s \n " ,
dosmode , smb_fname_str_dbg ( smb_fname ) ) ) ;
2007-12-27 23:31:08 +03:00
2009-07-07 01:36:16 +04:00
if ( ! VALID_STAT ( smb_fname - > st ) ) {
if ( SMB_VFS_STAT ( conn , smb_fname ) )
2001-01-09 23:34:37 +03:00
return ( - 1 ) ;
}
1998-08-17 11:40:06 +04:00
2009-07-07 01:36:16 +04:00
unixmode = smb_fname - > st . st_ex_mode ;
2007-12-27 23:31:08 +03:00
2009-07-07 01:36:16 +04:00
get_acl_group_bits ( conn , smb_fname - > base_name ,
& smb_fname - > st . st_ex_mode ) ;
2003-11-26 02:25:42 +03:00
2009-07-07 01:36:16 +04:00
if ( S_ISDIR ( smb_fname - > st . st_ex_mode ) )
2001-01-09 23:34:37 +03:00
dosmode | = aDIR ;
2002-03-05 04:43:50 +03:00
else
dosmode & = ~ aDIR ;
1998-08-17 11:40:06 +04:00
2009-07-08 23:24:03 +04:00
old_mode = dos_mode ( conn , smb_fname ) ;
2009-05-24 23:46:53 +04:00
2008-02-06 09:09:23 +03:00
if ( dosmode & FILE_ATTRIBUTE_OFFLINE ) {
if ( ! ( old_mode & FILE_ATTRIBUTE_OFFLINE ) ) {
2009-07-08 23:24:03 +04:00
lret = SMB_VFS_SET_OFFLINE ( conn , smb_fname - > base_name ) ;
2008-02-06 09:09:23 +03:00
if ( lret = = - 1 ) {
2009-07-07 01:36:16 +04:00
DEBUG ( 0 , ( " set_dos_mode: client has asked to "
" set FILE_ATTRIBUTE_OFFLINE to "
" %s/%s but there was an error while "
" setting it or it is not "
" supported. \n " , parent_dir ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2008-02-06 09:09:23 +03:00
}
}
}
dosmode & = ~ FILE_ATTRIBUTE_OFFLINE ;
old_mode & = ~ FILE_ATTRIBUTE_OFFLINE ;
if ( old_mode = = dosmode ) {
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_mode = unixmode ;
2001-01-09 23:34:37 +03:00
return ( 0 ) ;
2007-12-27 23:31:08 +03:00
}
1998-08-17 11:40:06 +04:00
2008-11-06 00:40:03 +03:00
# ifdef HAVE_STAT_DOS_FLAGS
{
bool attributes_changed ;
2009-07-07 01:36:16 +04:00
if ( set_stat_dos_flags ( conn , smb_fname , dosmode ,
2008-11-06 00:40:03 +03:00
& attributes_changed ) )
{
if ( ! newfile & & attributes_changed ) {
notify_fname ( conn , NOTIFY_ACTION_MODIFIED ,
2009-07-08 23:24:03 +04:00
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
smb_fname - > base_name ) ;
2008-11-06 00:40:03 +03:00
}
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_mode = unixmode ;
2008-11-06 00:40:03 +03:00
return 0 ;
}
}
# endif
2004-04-02 22:46:19 +04:00
/* Store the DOS attributes in an EA by preference. */
2009-07-08 23:24:03 +04:00
if ( set_ea_dos_attribute ( conn , smb_fname , dosmode ) ) {
2007-11-01 01:45:45 +03:00
if ( ! newfile ) {
notify_fname ( conn , NOTIFY_ACTION_MODIFIED ,
2009-07-08 23:24:03 +04:00
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
smb_fname - > base_name ) ;
2007-11-01 01:45:45 +03:00
}
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_mode = unixmode ;
2004-04-02 22:46:19 +04:00
return 0 ;
}
2009-07-08 06:20:22 +04:00
unixmode = unix_mode ( conn , dosmode , smb_fname , parent_dir ) ;
1998-08-17 11:40:06 +04:00
2001-01-09 23:34:37 +03:00
/* preserve the s bits */
mask | = ( S_ISUID | S_ISGID ) ;
1998-08-17 11:40:06 +04:00
2001-01-09 23:34:37 +03:00
/* preserve the t bit */
1998-08-17 11:40:06 +04:00
# ifdef S_ISVTX
2001-01-09 23:34:37 +03:00
mask | = S_ISVTX ;
1998-08-17 11:40:06 +04:00
# endif
2001-01-09 23:34:37 +03:00
/* possibly preserve the x bits */
if ( ! MAP_ARCHIVE ( conn ) )
mask | = S_IXUSR ;
if ( ! MAP_SYSTEM ( conn ) )
mask | = S_IXGRP ;
if ( ! MAP_HIDDEN ( conn ) )
mask | = S_IXOTH ;
2009-07-07 01:36:16 +04:00
unixmode | = ( smb_fname - > st . st_ex_mode & mask ) ;
2001-01-09 23:34:37 +03:00
/* if we previously had any r bits set then leave them alone */
2009-07-07 01:36:16 +04:00
if ( ( tmp = smb_fname - > st . st_ex_mode & ( S_IRUSR | S_IRGRP | S_IROTH ) ) ) {
2001-01-09 23:34:37 +03:00
unixmode & = ~ ( S_IRUSR | S_IRGRP | S_IROTH ) ;
unixmode | = tmp ;
}
/* if we previously had any w bits set then leave them alone
whilst adding in the new w bits , if the new mode is not rdonly */
if ( ! IS_DOS_READONLY ( dosmode ) ) {
2009-07-07 01:36:16 +04:00
unixmode | = ( smb_fname - > st . st_ex_mode & ( S_IWUSR | S_IWGRP | S_IWOTH ) ) ;
2001-01-09 23:34:37 +03:00
}
2009-07-08 23:24:03 +04:00
ret = SMB_VFS_CHMOD ( conn , smb_fname - > base_name , unixmode ) ;
2008-01-16 12:17:03 +03:00
if ( ret = = 0 ) {
if ( ! newfile | | ( lret ! = - 1 ) ) {
2007-11-01 01:45:45 +03:00
notify_fname ( conn , NOTIFY_ACTION_MODIFIED ,
2009-07-08 23:24:03 +04:00
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
smb_fname - > base_name ) ;
2007-11-01 01:45:45 +03:00
}
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_mode = unixmode ;
2001-01-18 02:47:08 +03:00
return 0 ;
2007-01-17 19:23:45 +03:00
}
2001-01-09 23:34:37 +03:00
2001-01-18 02:47:08 +03:00
if ( ( errno ! = EPERM ) & & ( errno ! = EACCES ) )
2001-01-09 23:34:37 +03:00
return - 1 ;
if ( ! lp_dos_filemode ( SNUM ( conn ) ) )
return - 1 ;
/* We want DOS semantics, ie allow non owner with write permission to change the
2007-03-06 02:40:03 +03:00
bits on a file . Just like file_ntimes below .
2001-01-09 23:34:37 +03:00
*/
/* Check if we have write access. */
if ( CAN_WRITE ( conn ) ) {
2001-04-14 04:19:12 +04:00
/*
* 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 fchmod .
* This file open does * not * break any oplocks we are
* holding . We need to review this . . . . may need to
* break batch oplocks open by others . JRA .
*/
2006-07-11 22:01:26 +04:00
files_struct * fsp ;
2009-07-08 23:24:03 +04:00
if ( ! NT_STATUS_IS_OK ( open_file_fchmod ( NULL , conn , smb_fname ,
& fsp ) ) )
2001-04-14 04:19:12 +04:00
return - 1 ;
become_root ( ) ;
2008-01-07 15:44:37 +03:00
ret = SMB_VFS_FCHMOD ( fsp , unixmode ) ;
2001-04-14 04:19:12 +04:00
unbecome_root ( ) ;
2008-10-09 18:27:49 +04:00
close_file_fchmod ( NULL , fsp ) ;
2007-11-01 01:45:45 +03:00
if ( ! newfile ) {
notify_fname ( conn , NOTIFY_ACTION_MODIFIED ,
2009-07-08 23:24:03 +04:00
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
smb_fname - > base_name ) ;
2007-11-01 01:45:45 +03:00
}
2007-12-27 23:31:08 +03:00
if ( ret = = 0 ) {
2009-07-07 01:36:16 +04:00
smb_fname - > st . st_ex_mode = unixmode ;
2007-12-27 23:31:08 +03:00
}
2001-01-09 23:34:37 +03:00
}
return ( ret ) ;
1998-08-17 11:40:06 +04:00
}
1998-08-17 17:11:34 +04:00
/*******************************************************************
2007-03-06 02:40:03 +03:00
Wrapper around the VFS ntimes that possibly allows DOS semantics rather
2004-04-01 02:46:15 +04:00
than POSIX .
1998-08-17 17:11:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-04-01 02:46:15 +04:00
2009-07-03 00:39:20 +04:00
int file_ntimes ( connection_struct * conn , const struct smb_filename * smb_fname ,
struct smb_file_time * ft )
1998-08-17 17:11:34 +04:00
{
2004-04-01 02:46:15 +04:00
int ret = - 1 ;
errno = 0 ;
2008-03-12 17:39:38 +03:00
DEBUG ( 6 , ( " file_ntime: actime: %s " ,
2009-01-24 01:40:19 +03:00
time_to_asc ( convert_timespec_to_time_t ( ft - > atime ) ) ) ) ;
2008-03-12 17:39:38 +03:00
DEBUG ( 6 , ( " file_ntime: modtime: %s " ,
2009-01-24 01:40:19 +03:00
time_to_asc ( convert_timespec_to_time_t ( ft - > mtime ) ) ) ) ;
2009-07-31 01:27:32 +04:00
DEBUG ( 6 , ( " file_ntime: ctime: %s " ,
time_to_asc ( convert_timespec_to_time_t ( ft - > ctime ) ) ) ) ;
2009-01-24 01:40:19 +03:00
DEBUG ( 6 , ( " file_ntime: createtime: %s " ,
time_to_asc ( convert_timespec_to_time_t ( ft - > create_time ) ) ) ) ;
2008-03-12 17:39:38 +03:00
2005-09-17 00:06:10 +04:00
/* Don't update the time on read-only shares */
/* We need this as set_filetime (which can be called on
close and other paths ) can end up calling this function
without the NEED_WRITE protection . Found by :
Leo Weppelman < leo @ wau . mis . ah . nl >
*/
if ( ! CAN_WRITE ( conn ) ) {
return 0 ;
}
2009-07-03 00:39:20 +04:00
if ( SMB_VFS_NTIMES ( conn , smb_fname , ft ) = = 0 ) {
2004-04-01 02:46:15 +04:00
return 0 ;
2007-03-06 02:40:03 +03:00
}
2004-04-01 02:46:15 +04:00
2007-03-06 02:40:03 +03:00
if ( ( errno ! = EPERM ) & & ( errno ! = EACCES ) ) {
2004-04-01 02:46:15 +04:00
return - 1 ;
2007-03-06 02:40:03 +03:00
}
2004-04-01 02:46:15 +04:00
2007-03-06 02:40:03 +03:00
if ( ! lp_dos_filetimes ( SNUM ( conn ) ) ) {
2004-04-01 02:46:15 +04:00
return - 1 ;
2007-03-06 02:40:03 +03:00
}
2004-04-01 02:46:15 +04:00
/* We have permission (given by the Samba admin) to
break POSIX semantics and allow a user to change
the time on a file they don ' t own but can write to
( as DOS does ) .
*/
/* Check if we have write access. */
2009-06-26 05:19:09 +04:00
if ( can_write_to_file ( conn , smb_fname ) ) {
2005-03-25 01:34:28 +03:00
/* We are allowed to become root and change the filetime. */
become_root ( ) ;
2009-07-03 00:39:20 +04:00
ret = SMB_VFS_NTIMES ( conn , smb_fname , ft ) ;
2005-03-25 01:34:28 +03:00
unbecome_root ( ) ;
2004-04-01 02:46:15 +04:00
}
return ret ;
1998-08-17 17:11:34 +04:00
}
2007-11-01 02:32:48 +03:00
2008-09-06 06:00:48 +04:00
/******************************************************************
Force a " sticky " write time on a pathname . This will always be
returned on all future write time queries and set on close .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-04-01 02:46:15 +04:00
2009-07-08 04:27:50 +04:00
bool set_sticky_write_time_path ( struct file_id fileid , struct timespec mtime )
1998-08-17 17:11:34 +04:00
{
2007-03-06 02:40:03 +03:00
if ( null_timespec ( mtime ) ) {
2008-03-12 17:39:38 +03:00
return true ;
2007-03-06 02:40:03 +03:00
}
1998-08-17 17:11:34 +04:00
2008-09-06 06:00:48 +04:00
if ( ! set_sticky_write_time ( fileid , mtime ) ) {
2008-03-12 17:39:38 +03:00
return false ;
2004-04-01 02:46:15 +04:00
}
2007-01-17 19:23:45 +03:00
2007-11-01 02:32:48 +03:00
return true ;
2007-03-06 02:40:03 +03:00
}
2008-03-12 17:39:38 +03:00
2008-09-06 06:00:48 +04:00
/******************************************************************
Force a " sticky " write time on an fsp . This will always be
returned on all future write time queries and set on close .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-08 04:27:50 +04:00
bool set_sticky_write_time_fsp ( struct files_struct * fsp , struct timespec mtime )
2008-03-12 17:39:38 +03:00
{
2008-09-06 06:00:48 +04:00
fsp - > write_time_forced = true ;
TALLOC_FREE ( fsp - > update_write_time_event ) ;
2009-07-02 21:27:01 +04:00
return set_sticky_write_time_path ( fsp - > file_id , mtime ) ;
2008-09-06 06:00:48 +04:00
}
/******************************************************************
Update a write time immediately , without the 2 second delay .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool update_write_time ( struct files_struct * fsp )
{
if ( ! set_write_time ( fsp - > file_id , timespec_current ( ) ) ) {
return false ;
2008-03-12 17:39:38 +03:00
}
2008-09-06 06:00:48 +04:00
notify_fname ( fsp - > conn , NOTIFY_ACTION_MODIFIED ,
2009-07-11 01:50:37 +04:00
FILE_NOTIFY_CHANGE_LAST_WRITE , fsp - > fsp_name - > base_name ) ;
2008-09-06 06:00:48 +04:00
return true ;
2008-03-12 17:39:38 +03:00
}
2009-08-11 02:07:53 +04:00
/******************************************************************
2009-08-13 00:00:54 +04:00
Set a create time EA .
2009-08-11 02:07:53 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-08-13 00:00:54 +04:00
NTSTATUS set_create_timespec_ea ( connection_struct * conn ,
struct files_struct * fsp ,
const struct smb_filename * smb_fname ,
struct timespec create_time )
{
int ret ;
char buf [ 8 ] ;
if ( ! lp_store_create_time ( SNUM ( conn ) ) ) {
return NT_STATUS_OK ;
}
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , buf , create_time ) ;
2009-08-13 00:00:54 +04:00
if ( fsp & & fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FSETXATTR ( fsp ,
SAMBA_XATTR_DOSTIMESTAMPS ,
buf ,
sizeof ( buf ) ,
0 ) ;
} else {
ret = SMB_VFS_SETXATTR ( conn ,
smb_fname - > base_name ,
SAMBA_XATTR_DOSTIMESTAMPS ,
buf ,
sizeof ( buf ) ,
0 ) ;
}
if ( ret = = - 1 ) {
map_nt_error_from_unix ( errno ) ;
}
2009-08-13 02:08:23 +04:00
DEBUG ( 10 , ( " set_create_timespec_ea: wrote create time EA for file %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2009-08-13 00:00:54 +04:00
return NT_STATUS_OK ;
}
/******************************************************************
Returns an EA create timespec , or a zero timespec if fail .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct timespec get_create_timespec_ea ( connection_struct * conn ,
struct files_struct * fsp ,
const struct smb_filename * smb_fname )
{
ssize_t ret ;
char buf [ 8 ] ;
struct timespec ts ;
ZERO_STRUCT ( ts ) ;
if ( ! lp_store_create_time ( SNUM ( conn ) ) ) {
return ts ;
}
if ( fsp & & fsp - > fh - > fd ! = - 1 ) {
ret = SMB_VFS_FGETXATTR ( fsp ,
SAMBA_XATTR_DOSTIMESTAMPS ,
buf ,
sizeof ( buf ) ) ;
} else {
ret = SMB_VFS_GETXATTR ( conn ,
smb_fname - > base_name ,
SAMBA_XATTR_DOSTIMESTAMPS ,
buf ,
sizeof ( buf ) ) ;
}
if ( ret = = sizeof ( buf ) ) {
return interpret_long_date ( buf ) ;
} else {
return ts ;
}
}
/******************************************************************
Return a create time - looks at EA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct timespec get_create_timespec ( connection_struct * conn ,
struct files_struct * fsp ,
2009-08-11 02:07:53 +04:00
const struct smb_filename * smb_fname )
{
2009-08-13 00:00:54 +04:00
struct timespec ts = get_create_timespec_ea ( conn , fsp , smb_fname ) ;
if ( ! null_timespec ( ts ) ) {
return ts ;
} else {
return smb_fname - > st . st_ex_btime ;
}
2009-08-11 02:07:53 +04:00
}
/******************************************************************
Return a change time ( may look at EA in future ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-08-13 00:00:54 +04:00
struct timespec get_change_timespec ( connection_struct * conn ,
struct files_struct * fsp ,
2009-08-11 02:07:53 +04:00
const struct smb_filename * smb_fname )
{
return smb_fname - > st . st_ex_mtime ;
}