2004-09-18 12:16:14 +04:00
/*
Unix SMB / CIFS implementation .
POSIX NTVFS backend -
Copyright ( C ) Andrew Tridgell 2004
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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-09-18 12:16:14 +04:00
( at your option ) any later version .
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 .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-09-18 12:16:14 +04:00
*/
2004-11-05 10:29:02 +03:00
# include "includes.h"
2004-09-18 12:16:14 +04:00
# include "vfs_posix.h"
2020-08-05 03:49:42 +03:00
# include "lib/util/time.h"
2004-09-18 12:16:14 +04:00
2004-09-20 11:28:43 +04:00
/****************************************************************************
Change a unix mode to a dos mode .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32_t dos_mode_from_stat ( struct pvfs_state * pvfs , struct stat * st )
2004-09-18 12:16:14 +04:00
{
2004-09-20 11:28:43 +04:00
int result = 0 ;
if ( ( st - > st_mode & S_IWUSR ) = = 0 )
result | = FILE_ATTRIBUTE_READONLY ;
2004-11-05 14:31:35 +03:00
if ( ( pvfs - > flags & PVFS_FLAG_MAP_ARCHIVE ) & & ( ( st - > st_mode & S_IXUSR ) ! = 0 ) )
result | = FILE_ATTRIBUTE_ARCHIVE ;
if ( ( pvfs - > flags & PVFS_FLAG_MAP_SYSTEM ) & & ( ( st - > st_mode & S_IXGRP ) ! = 0 ) )
result | = FILE_ATTRIBUTE_SYSTEM ;
if ( ( pvfs - > flags & PVFS_FLAG_MAP_HIDDEN ) & & ( ( st - > st_mode & S_IXOTH ) ! = 0 ) )
result | = FILE_ATTRIBUTE_HIDDEN ;
2004-09-20 11:28:43 +04:00
if ( S_ISDIR ( st - > st_mode ) )
result = FILE_ATTRIBUTE_DIRECTORY | ( result & FILE_ATTRIBUTE_READONLY ) ;
return result ;
}
2004-09-18 12:16:14 +04:00
2004-09-20 11:28:43 +04:00
/*
fill in the dos file attributes for a file
*/
2008-05-05 14:18:47 +04:00
NTSTATUS pvfs_fill_dos_info ( struct pvfs_state * pvfs , struct pvfs_filename * name ,
2010-01-05 20:42:54 +03:00
unsigned int flags , int fd )
2004-09-20 11:28:43 +04:00
{
2008-05-05 14:18:47 +04:00
NTSTATUS status ;
DATA_BLOB lkey ;
NTTIME write_time ;
2006-02-28 06:47:02 +03:00
/* make directories appear as size 0 with 1 link */
2004-10-25 11:03:15 +04:00
if ( S_ISDIR ( name - > st . st_mode ) ) {
name - > st . st_size = 0 ;
2006-02-28 06:47:02 +03:00
name - > st . st_nlink = 1 ;
2008-05-23 11:46:50 +04:00
} else if ( name - > stream_id = = 0 ) {
name - > stream_name = NULL ;
2004-10-25 11:03:15 +04:00
}
2004-09-20 11:28:43 +04:00
/* for now just use the simple samba mapping */
unix_to_nt_time ( & name - > dos . create_time , name - > st . st_ctime ) ;
unix_to_nt_time ( & name - > dos . access_time , name - > st . st_atime ) ;
2004-10-26 11:11:49 +04:00
unix_to_nt_time ( & name - > dos . write_time , name - > st . st_mtime ) ;
unix_to_nt_time ( & name - > dos . change_time , name - > st . st_ctime ) ;
2020-08-05 03:49:42 +03:00
name - > dos . create_time + = get_ctimensec ( & name - > st ) / 100 ;
name - > dos . access_time + = get_atimensec ( & name - > st ) / 100 ;
name - > dos . write_time + = get_mtimensec ( & name - > st ) / 100 ;
name - > dos . change_time + = get_ctimensec ( & name - > st ) / 100 ;
2004-09-20 11:28:43 +04:00
name - > dos . attrib = dos_mode_from_stat ( pvfs , & name - > st ) ;
2004-11-17 10:17:55 +03:00
name - > dos . alloc_size = pvfs_round_alloc_size ( pvfs , name - > st . st_size ) ;
2004-09-20 11:28:43 +04:00
name - > dos . nlink = name - > st . st_nlink ;
2012-08-20 03:49:30 +04:00
name - > dos . ea_size = 4 ; /* TODO: Fill this in without hitting the stream bad in pvfs_doseas_load() */
2011-09-05 15:10:42 +04:00
if ( pvfs - > ntvfs - > ctx - > protocol > = PROTOCOL_SMB2_02 ) {
2008-05-22 18:07:12 +04:00
/* SMB2 represents a null EA with zero bytes */
name - > dos . ea_size = 0 ;
}
2004-09-20 11:28:43 +04:00
name - > dos . file_id = ( ( ( uint64_t ) name - > st . st_dev ) < < 32 ) | name - > st . st_ino ;
2004-11-24 09:09:14 +03:00
name - > dos . flags = 0 ;
2004-09-18 12:16:14 +04:00
2008-05-05 14:18:47 +04:00
status = pvfs_dosattrib_load ( pvfs , name , fd ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
if ( flags & PVFS_RESOLVE_NO_OPENDB ) {
return NT_STATUS_OK ;
}
status = pvfs_locking_key ( name , name , & lkey ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
status = odb_get_file_infos ( pvfs - > odb_context , & lkey ,
NULL , & write_time ) ;
data_blob_free ( & lkey ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " WARNING: odb_get_file_infos: %s \n " , nt_errstr ( status ) ) ) ;
return status ;
}
if ( ! null_time ( write_time ) ) {
name - > dos . write_time = write_time ;
}
return NT_STATUS_OK ;
2004-09-18 12:16:14 +04:00
}
2004-10-25 09:27:49 +04:00
/*
return a set of unix file permissions for a new file or directory
*/
2005-01-31 19:06:21 +03:00
mode_t pvfs_fileperms ( struct pvfs_state * pvfs , uint32_t attrib )
2004-10-25 09:27:49 +04:00
{
2007-07-04 08:16:16 +04:00
mode_t mode = ( S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH ) ;
2004-10-25 09:27:49 +04:00
2007-07-04 08:16:16 +04:00
if ( ! ( pvfs - > flags & PVFS_FLAG_XATTR_ENABLE ) & &
( attrib & FILE_ATTRIBUTE_READONLY ) ) {
mode & = ~ ( S_IWUSR | S_IWGRP | S_IWOTH ) ;
2004-10-25 09:27:49 +04:00
}
2004-11-05 10:29:02 +03:00
if ( ! ( pvfs - > flags & PVFS_FLAG_XATTR_ENABLE ) ) {
if ( ( attrib & FILE_ATTRIBUTE_ARCHIVE ) & &
( pvfs - > flags & PVFS_FLAG_MAP_ARCHIVE ) ) {
mode | = S_IXUSR ;
}
if ( ( attrib & FILE_ATTRIBUTE_SYSTEM ) & &
( pvfs - > flags & PVFS_FLAG_MAP_SYSTEM ) ) {
mode | = S_IXGRP ;
}
if ( ( attrib & FILE_ATTRIBUTE_HIDDEN ) & &
( pvfs - > flags & PVFS_FLAG_MAP_HIDDEN ) ) {
mode | = S_IXOTH ;
}
2004-10-25 09:27:49 +04:00
}
2007-07-04 08:16:16 +04:00
if ( attrib & FILE_ATTRIBUTE_DIRECTORY ) {
mode | = ( S_IFDIR | S_IWUSR ) ;
mode | = ( S_IXUSR | S_IXGRP | S_IXOTH ) ;
mode & = pvfs - > options . dir_mask ;
mode | = pvfs - > options . force_dir_mode ;
} else {
mode & = pvfs - > options . create_mask ;
mode | = pvfs - > options . force_create_mode ;
}
2004-10-25 09:27:49 +04:00
return mode ;
}
2004-11-17 08:58:04 +03:00
2007-07-04 08:16:16 +04:00