2016-01-14 13:51:39 +03:00
/*
2002-07-15 14:35:28 +04:00
Unix SMB / Netbios implementation .
Version 1.9 .
1998-08-17 11:15:54 +04:00
read / write to a files_struct
Copyright ( C ) Andrew Tridgell 1992 - 1998
2002-07-15 14:35:28 +04:00
Copyright ( C ) Jeremy Allison 2000 - 2002. - write cache .
2016-01-14 13:51:39 +03:00
1998-08-17 11:15:54 +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:15:54 +04:00
( at your option ) any later version .
2016-01-14 13:51:39 +03:00
1998-08-17 11:15:54 +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 .
2016-01-14 13:51:39 +03:00
1998-08-17 11:15:54 +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:15:54 +04:00
*/
# include "includes.h"
2010-05-04 12:28:48 +04:00
# include "printing.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
2011-04-14 02:36:23 +04:00
# include "smbprofile.h"
1998-08-17 11:15:54 +04:00
/****************************************************************************
2002-07-15 14:35:28 +04:00
Read from a file .
1998-08-17 11:15:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-11 05:24:30 +04:00
2012-04-05 08:53:08 +04:00
ssize_t read_file ( files_struct * fsp , char * data , off_t pos , size_t n )
1998-08-17 11:15:54 +04:00
{
2012-06-08 18:06:24 +04:00
ssize_t ret = 0 ;
1998-08-17 11:15:54 +04:00
2001-11-25 11:26:37 +03:00
/* you can't read from print files */
2005-05-09 03:16:28 +04:00
if ( fsp - > print_file ) {
2009-07-11 05:23:00 +04:00
errno = EBADF ;
2001-11-25 11:26:37 +03:00
return - 1 ;
2005-05-09 03:16:28 +04:00
}
2000-04-16 10:22:31 +04:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = pos ;
2004-01-06 04:22:14 +03:00
2001-11-25 11:26:37 +03:00
if ( n > 0 ) {
2012-06-08 18:06:24 +04:00
ret = SMB_VFS_PREAD ( fsp , data , n , pos ) ;
2004-01-06 04:22:14 +03:00
2012-06-08 18:06:24 +04:00
if ( ret = = - 1 ) {
2001-11-25 11:26:37 +03:00
return - 1 ;
}
}
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " read_file (%s): pos = %.0f, size = %lu, returned %lu \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , ( double ) pos , ( unsigned long ) n , ( long ) ret ) ) ;
2002-07-15 14:35:28 +04:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos + = ret ;
fsp - > fh - > position_information = fsp - > fh - > pos ;
2003-08-15 01:16:06 +04:00
2001-11-25 11:26:37 +03:00
return ( ret ) ;
1998-08-17 11:15:54 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
2000-08-26 00:44:33 +04:00
* Really * write to a file .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-31 02:22:24 +03:00
static ssize_t real_write_file ( struct smb_request * req ,
files_struct * fsp ,
const char * data ,
2012-04-05 08:53:08 +04:00
off_t pos ,
2007-10-31 02:22:24 +03:00
size_t n )
1999-12-13 16:27:58 +03:00
{
2002-07-15 14:35:28 +04:00
ssize_t ret ;
2018-05-03 02:39:16 +03:00
fsp - > fh - > pos = pos ;
2020-04-02 11:29:15 +03:00
if ( pos & &
lp_strict_allocate ( SNUM ( fsp - > conn ) ) & &
! fsp - > is_sparse )
{
2018-05-03 02:39:16 +03:00
if ( vfs_fill_sparse ( fsp , pos ) = = - 1 ) {
return - 1 ;
2005-05-17 05:04:51 +04:00
}
2004-01-06 04:22:14 +03:00
}
2018-05-03 02:39:16 +03:00
ret = vfs_pwrite_data ( req , fsp , data , n , pos ) ;
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " real_write_file (%s): pos = %.0f, size = %lu, returned %ld \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , ( double ) pos , ( unsigned long ) n , ( long ) ret ) ) ;
1999-12-13 16:27:58 +03:00
2003-08-15 01:16:06 +04:00
if ( ret ! = - 1 ) {
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos + = ret ;
2003-08-15 01:16:06 +04:00
/* Yes - this is correct - writes don't update this. JRA. */
/* Found by Samba4 tests. */
#if 0
fsp - > position_information = fsp - > pos ;
# endif
}
2002-07-15 14:35:28 +04:00
return ret ;
1999-12-13 16:27:58 +03:00
}
1998-08-17 11:15:54 +04:00
2018-05-23 10:41:29 +03:00
void fsp_flush_write_time_update ( struct files_struct * fsp )
2008-03-12 17:39:38 +03:00
{
2018-05-23 10:41:29 +03:00
/*
* Note this won ' t expect any impersonation !
* So don ' t call any SMB_VFS operations here !
*/
2008-03-12 17:39:38 +03:00
2009-07-11 01:50:37 +04:00
DEBUG ( 5 , ( " Update write time on %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2008-03-12 17:39:38 +03:00
2020-03-15 10:30:21 +03:00
trigger_write_time_update_immediate ( fsp ) ;
2008-03-12 17:39:38 +03:00
}
2018-05-23 10:41:29 +03:00
static void update_write_time_handler ( struct tevent_context * ctx ,
struct tevent_timer * te ,
struct timeval now ,
void * private_data )
{
files_struct * fsp = ( files_struct * ) private_data ;
fsp_flush_write_time_update ( fsp ) ;
}
2008-09-06 06:00:48 +04:00
/*********************************************************
Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
in the future .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-03-12 17:39:38 +03:00
void trigger_write_time_update ( struct files_struct * fsp )
{
2008-04-07 11:27:22 +04:00
int delay ;
2015-11-27 20:29:55 +03:00
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) {
2009-07-02 04:39:10 +04:00
/* Don't use delayed writes on POSIX files. */
return ;
}
2008-03-12 17:39:38 +03:00
if ( fsp - > write_time_forced ) {
2008-09-06 06:00:48 +04:00
/* No point - "sticky" write times
* in effect .
*/
2008-03-12 17:39:38 +03:00
return ;
}
2009-11-06 03:20:11 +03:00
/* We need to remember someone did a write
* and update to current time on close . */
fsp - > update_write_time_on_close = true ;
2008-09-08 17:12:24 +04:00
if ( fsp - > update_write_time_triggered ) {
2008-09-06 06:00:48 +04:00
/*
2009-11-06 03:20:11 +03:00
* We only update the write time after 2 seconds
* on the first normal write . After that
* no other writes affect this until close .
2008-09-06 06:00:48 +04:00
*/
2008-03-12 17:39:38 +03:00
return ;
}
2008-09-08 17:12:24 +04:00
fsp - > update_write_time_triggered = true ;
2008-03-12 17:39:38 +03:00
2008-04-07 11:27:22 +04:00
delay = lp_parm_int ( SNUM ( fsp - > conn ) ,
" smbd " , " writetimeupdatedelay " ,
WRITE_TIME_UPDATE_USEC_DELAY ) ;
2009-11-06 03:20:11 +03:00
DEBUG ( 5 , ( " Update write time %d usec later on %s \n " ,
delay , fsp_str_dbg ( fsp ) ) ) ;
2018-12-27 17:26:03 +03:00
/* trigger the update 2 seconds later */
2008-03-12 17:39:38 +03:00
fsp - > update_write_time_event =
2018-12-27 17:26:03 +03:00
tevent_add_timer ( fsp - > conn - > sconn - > ev_ctx , NULL ,
2011-12-12 16:39:56 +04:00
timeval_current_ofs_usec ( delay ) ,
update_write_time_handler , fsp ) ;
2008-03-12 17:39:38 +03:00
}
2008-09-06 06:00:48 +04:00
void trigger_write_time_update_immediate ( struct files_struct * fsp )
{
2009-11-06 03:20:11 +03:00
struct smb_file_time ft ;
2019-12-02 18:30:50 +03:00
init_smb_file_time ( & ft ) ;
2015-11-27 20:29:55 +03:00
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) {
2009-07-02 04:39:10 +04:00
/* Don't use delayed writes on POSIX files. */
return ;
}
2008-09-06 06:00:48 +04:00
if ( fsp - > write_time_forced ) {
/*
* No point - " sticky " write times
* in effect .
*/
return ;
}
2008-09-08 17:12:24 +04:00
TALLOC_FREE ( fsp - > update_write_time_event ) ;
2009-07-11 01:50:37 +04:00
DEBUG ( 5 , ( " Update write time immediate on %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
2008-09-08 17:12:24 +04:00
2009-11-06 03:20:11 +03:00
/* After an immediate update, reset the trigger. */
2008-09-08 17:12:24 +04:00
fsp - > update_write_time_triggered = true ;
fsp - > update_write_time_on_close = false ;
2009-11-06 03:20:11 +03:00
2019-12-02 18:30:50 +03:00
ft . mtime = timespec_current ( ) ;
2009-11-06 03:20:11 +03:00
/* Update the time in the open file db. */
( void ) set_write_time ( fsp - > file_id , ft . mtime ) ;
/* Now set on disk - takes care of notify. */
( void ) smb_set_file_time ( fsp - > conn , fsp , fsp - > fsp_name , & ft , false ) ;
2008-09-06 06:00:48 +04:00
}
2012-07-12 18:28:11 +04:00
void mark_file_modified ( files_struct * fsp )
{
int dosmode ;
2020-03-15 10:30:21 +03:00
trigger_write_time_update ( fsp ) ;
2012-07-12 18:28:11 +04:00
if ( fsp - > modified ) {
return ;
}
fsp - > modified = true ;
2015-11-27 20:29:55 +03:00
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) {
2012-07-12 18:28:11 +04:00
return ;
}
if ( ! ( lp_store_dos_attributes ( SNUM ( fsp - > conn ) ) | |
MAP_ARCHIVE ( fsp - > conn ) ) ) {
return ;
}
dosmode = dos_mode ( fsp - > conn , fsp - > fsp_name ) ;
if ( IS_DOS_ARCHIVE ( dosmode ) ) {
return ;
}
file_set_dosmode ( fsp - > conn , fsp - > fsp_name ,
dosmode | FILE_ATTRIBUTE_ARCHIVE , NULL , false ) ;
}
2005-05-09 03:16:28 +04:00
/****************************************************************************
Write to a file .
1998-08-17 11:15:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-11 05:24:30 +04:00
2007-10-31 02:22:24 +03:00
ssize_t write_file ( struct smb_request * req ,
files_struct * fsp ,
const char * data ,
2012-04-05 08:53:08 +04:00
off_t pos ,
2007-10-31 02:22:24 +03:00
size_t n )
1998-08-17 11:15:54 +04:00
{
2002-07-15 14:35:28 +04:00
ssize_t total_written = 0 ;
2002-12-05 07:00:16 +03:00
if ( fsp - > print_file ) {
2010-05-04 12:28:48 +04:00
uint32_t t ;
int ret ;
2002-12-05 07:00:16 +03:00
2010-05-04 12:28:48 +04:00
ret = print_spool_write ( fsp , data , n , pos , & t ) ;
if ( ret ) {
errno = ret ;
2002-12-05 07:00:16 +03:00
return - 1 ;
}
2010-05-04 12:28:48 +04:00
return t ;
2002-12-05 07:00:16 +03:00
}
2002-07-15 14:35:28 +04:00
if ( ! fsp - > can_write ) {
errno = EPERM ;
2006-07-25 04:16:45 +04:00
return - 1 ;
2002-07-15 14:35:28 +04:00
}
2012-07-12 18:28:11 +04:00
mark_file_modified ( fsp ) ;
2002-07-15 14:35:28 +04:00
/*
* If this file is level II oplocked then we need
* to grab the shared memory lock and inform all
* other files with a level II lock that they need
* to flush their read caches . We keep the lock over
* the shared memory area whilst doing this .
*/
1999-12-13 16:27:58 +03:00
2009-02-03 22:56:35 +03:00
/* This should actually be improved to span the write. */
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_WRITE ) ;
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_WRITE ) ;
1999-12-13 16:27:58 +03:00
2019-05-27 12:24:14 +03:00
total_written = real_write_file ( req , fsp , data , pos , n ) ;
2002-07-15 14:35:28 +04:00
return total_written ;
1998-08-17 11:15:54 +04:00
}
1998-08-17 11:40:06 +04:00
/*******************************************************************
sync a file
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-11 05:24:30 +04:00
2007-10-19 04:40:25 +04:00
NTSTATUS sync_file ( connection_struct * conn , files_struct * fsp , bool write_through )
1998-08-17 11:40:06 +04:00
{
2005-09-03 11:19:28 +04:00
if ( fsp - > fh - > fd = = - 1 )
2007-06-15 23:24:04 +04:00
return NT_STATUS_INVALID_HANDLE ;
2005-09-03 11:19:28 +04:00
if ( lp_strict_sync ( SNUM ( conn ) ) & &
2014-02-04 06:09:12 +04:00
( lp_sync_always ( SNUM ( conn ) ) | | write_through ) ) {
2019-05-27 12:24:14 +03:00
int ret ;
2018-04-28 02:59:42 +03:00
ret = smb_vfs_fsync_sync ( fsp ) ;
2007-06-15 23:24:04 +04:00
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2002-07-15 14:35:28 +04:00
}
2007-06-15 23:24:04 +04:00
return NT_STATUS_OK ;
1998-08-17 11:40:06 +04:00
}