1998-08-17 11:15:54 +04: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 .
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 .
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 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"
2007-10-19 04:40:25 +04:00
static bool setup_write_cache ( files_struct * , SMB_OFF_T ) ;
1998-08-17 11:15:54 +04:00
1999-12-13 16:27:58 +03:00
/****************************************************************************
Read from write cache if we can .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool read_from_write_cache ( files_struct * fsp , char * data , SMB_OFF_T pos , size_t n )
1999-12-13 16:27:58 +03:00
{
2002-07-15 14:35:28 +04:00
write_cache * wcp = fsp - > wcp ;
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( ! wcp ) {
2002-07-15 14:35:28 +04:00
return False ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( n > wcp - > data_size | | pos < wcp - > offset | | pos + n > wcp - > offset + wcp - > data_size ) {
2002-07-15 14:35:28 +04:00
return False ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
memcpy ( data , wcp - > data + ( pos - wcp - > offset ) , n ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_read_hits ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
return True ;
1999-12-13 16:27:58 +03:00
}
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
ssize_t read_file ( files_struct * fsp , char * data , SMB_OFF_T pos , size_t n )
1998-08-17 11:15:54 +04:00
{
2001-11-25 11:26:37 +03:00
ssize_t ret = 0 , readret ;
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 ) {
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
2001-11-25 11:26:37 +03:00
/*
* Serve from write cache if we can .
*/
1999-12-13 16:27:58 +03:00
2003-08-15 01:16:06 +04:00
if ( read_from_write_cache ( fsp , data , pos , n ) ) {
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = pos + n ;
fsp - > fh - > position_information = fsp - > fh - > pos ;
2001-11-25 11:26:37 +03:00
return n ;
2003-08-15 01:16:06 +04:00
}
1998-08-17 11:15:54 +04:00
2001-11-25 11:26:37 +03:00
flush_write_cache ( fsp , READ_FLUSH ) ;
1998-08-17 11:15:54 +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 ) {
# ifdef DMF_FIX
int numretries = 3 ;
tryagain :
2008-01-07 02:14:19 +03:00
readret = SMB_VFS_PREAD ( fsp , data , n , pos ) ;
2004-01-06 04:22:14 +03:00
2001-11-25 11:26:37 +03:00
if ( readret = = - 1 ) {
if ( ( errno = = EAGAIN ) & & numretries ) {
DEBUG ( 3 , ( " read_file EAGAIN retry in 10 seconds \n " ) ) ;
( void ) sleep ( 10 ) ;
- - numretries ;
goto tryagain ;
}
return - 1 ;
}
# else /* NO DMF fix. */
2008-01-07 02:14:19 +03:00
readret = SMB_VFS_PREAD ( fsp , data , n , pos ) ;
2004-01-06 04:22:14 +03:00
2005-05-09 03:16:28 +04:00
if ( readret = = - 1 ) {
2001-11-25 11:26:37 +03:00
return - 1 ;
2005-05-09 03:16:28 +04:00
}
2001-11-25 11:26:37 +03:00
# endif
2005-05-09 03:16:28 +04:00
if ( readret > 0 ) {
2001-11-25 11:26:37 +03:00
ret + = readret ;
2005-05-09 03:16:28 +04:00
}
2001-11-25 11:26:37 +03:00
}
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " read_file (%s): pos = %.0f, size = %lu, returned %lu \n " ,
fsp - > fsp_name , ( double ) pos , ( unsigned long ) n , ( long ) ret ) ) ;
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
/* how many write cache buffers have been allocated */
static unsigned int allocated_write_caches ;
/****************************************************************************
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 ,
SMB_OFF_T pos ,
size_t n )
1999-12-13 16:27:58 +03:00
{
2002-07-15 14:35:28 +04:00
ssize_t ret ;
2005-05-09 03:16:28 +04:00
if ( pos = = - 1 ) {
2007-10-31 02:22:24 +03:00
ret = vfs_write_data ( req , fsp , data , n ) ;
2005-05-09 03:16:28 +04:00
} else {
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = pos ;
2005-05-17 05:04:51 +04:00
if ( pos & & lp_strict_allocate ( SNUM ( fsp - > conn ) ) ) {
if ( vfs_fill_sparse ( fsp , pos ) = = - 1 ) {
return - 1 ;
}
}
2007-10-31 02:22:24 +03:00
ret = vfs_pwrite_data ( req , fsp , data , n , pos ) ;
2004-01-06 04:22:14 +03:00
}
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " real_write_file (%s): pos = %.0f, size = %lu, returned %ld \n " ,
fsp - > fsp_name , ( 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
/****************************************************************************
2005-05-09 03:16:28 +04:00
File size cache change .
Updates size on disk but doesn ' t flush the cache .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int wcp_file_size_change ( files_struct * fsp )
{
int ret ;
write_cache * wcp = fsp - > wcp ;
wcp - > file_size = wcp - > offset + wcp - > data_size ;
2008-01-07 17:55:09 +03:00
ret = SMB_VFS_FTRUNCATE ( fsp , wcp - > file_size ) ;
2005-05-09 03:16:28 +04:00
if ( ret = = - 1 ) {
DEBUG ( 0 , ( " wcp_file_size_change (%s): ftruncate of size %.0f error %s \n " ,
fsp - > fsp_name , ( double ) wcp - > file_size , strerror ( errno ) ) ) ;
}
return ret ;
}
2008-03-12 17:39:38 +03:00
static void update_write_time_handler ( struct event_context * ctx ,
struct timed_event * te ,
const struct timeval * now ,
void * private_data )
{
2008-09-06 06:00:48 +04:00
files_struct * fsp = ( files_struct * ) private_data ;
2008-03-12 17:39:38 +03:00
2008-09-06 06:00:48 +04:00
/* Remove the timed event handler. */
TALLOC_FREE ( fsp - > update_write_time_event ) ;
DEBUG ( 5 , ( " Update write time on %s \n " , fsp - > fsp_name ) ) ;
2008-03-12 17:39:38 +03:00
2008-09-06 06:00:48 +04:00
/* change the write time if not already changed by someone else */
update_write_time ( fsp ) ;
2008-03-12 17:39:38 +03:00
}
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 ;
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 ;
}
2008-09-08 17:12:24 +04:00
if ( fsp - > update_write_time_triggered ) {
2008-09-06 06:00:48 +04:00
/*
2008-09-13 02:03:05 +04:00
* We only update the write time
* on the first write . After that
* no other writes affect this .
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 ) ;
2008-03-12 17:39:38 +03:00
/* trigger the update 2 seconds later */
fsp - > update_write_time_on_close = true ;
fsp - > update_write_time_event =
event_add_timed ( smbd_event_context ( ) , NULL ,
2008-04-07 11:27:22 +04:00
timeval_current_ofs ( 0 , delay ) ,
2008-03-12 17:39:38 +03:00
" update_write_time_handler " ,
update_write_time_handler , fsp ) ;
}
2008-09-06 06:00:48 +04:00
void trigger_write_time_update_immediate ( struct files_struct * fsp )
{
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 ) ;
DEBUG ( 5 , ( " Update write time immediate on %s \n " , fsp - > fsp_name ) ) ;
fsp - > update_write_time_triggered = true ;
2008-09-06 06:00:48 +04:00
2008-09-08 17:12:24 +04:00
fsp - > update_write_time_on_close = false ;
2008-09-06 06:00:48 +04:00
update_write_time ( fsp ) ;
}
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 ,
SMB_OFF_T pos ,
size_t n )
1998-08-17 11:15:54 +04:00
{
2002-07-15 14:35:28 +04:00
write_cache * wcp = fsp - > wcp ;
ssize_t total_written = 0 ;
2007-10-31 02:22:24 +03:00
int write_path = - 1 ;
2002-07-15 14:35:28 +04:00
2002-12-05 07:00:16 +03:00
if ( fsp - > print_file ) {
2004-10-19 21:05:01 +04:00
fstring sharename ;
2002-12-05 07:00:16 +03:00
uint32 jobid ;
2004-10-19 21:05:01 +04:00
if ( ! rap_to_pjobid ( fsp - > rap_print_jobid , sharename , & jobid ) ) {
2002-12-05 07:00:16 +03:00
DEBUG ( 3 , ( " write_file: Unable to map RAP jobid %u to jobid. \n " ,
( unsigned int ) fsp - > rap_print_jobid ) ) ;
errno = EBADF ;
return - 1 ;
}
2005-05-18 22:02:15 +04:00
return print_job_write ( SNUM ( fsp - > conn ) , jobid , data , pos , n ) ;
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
}
if ( ! fsp - > modified ) {
SMB_STRUCT_STAT st ;
fsp - > modified = True ;
2008-01-07 15:21:26 +03:00
if ( SMB_VFS_FSTAT ( fsp , & st ) = = 0 ) {
2008-03-12 17:39:38 +03:00
int dosmode ;
trigger_write_time_update ( fsp ) ;
dosmode = dos_mode ( fsp - > conn , fsp - > fsp_name , & st ) ;
2007-11-01 01:45:45 +03:00
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 ,
NULL ,
false ) ;
2004-04-02 22:46:19 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* If this is the first write and we have an exclusive oplock then setup
* the write cache .
*/
if ( EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) & & ! wcp ) {
setup_write_cache ( fsp , st . st_size ) ;
wcp = fsp - > wcp ;
2007-10-31 02:22:24 +03:00
}
}
2002-07-15 14:35:28 +04:00
}
1998-08-17 11:15:54 +04:00
2000-10-05 22:50:18 +04:00
# ifdef WITH_PROFILE
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_total_writes ) ;
if ( ! fsp - > oplock_type ) {
DO_PROFILE_INC ( writecache_non_oplock_writes ) ;
}
2000-10-05 22:50:18 +04:00
# endif
1999-12-13 16:27:58 +03:00
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
2002-07-15 14:35:28 +04:00
release_level_2_oplocks_on_change ( fsp ) ;
1999-12-13 16:27:58 +03:00
2000-10-05 22:50:18 +04:00
# ifdef WITH_PROFILE
2002-07-15 14:35:28 +04:00
if ( profile_p & & profile_p - > writecache_total_writes % 500 = = 0 ) {
DEBUG ( 3 , ( " WRITECACHE: initwrites=%u abutted=%u total=%u \
1999-12-13 16:27:58 +03:00
nonop = % u allocated = % u active = % u direct = % u perfect = % u readhits = % u \ n " ,
2002-07-15 14:35:28 +04:00
profile_p - > writecache_init_writes ,
profile_p - > writecache_abutted_writes ,
profile_p - > writecache_total_writes ,
profile_p - > writecache_non_oplock_writes ,
profile_p - > writecache_allocated_write_caches ,
profile_p - > writecache_num_write_caches ,
profile_p - > writecache_direct_writes ,
profile_p - > writecache_num_perfect_writes ,
profile_p - > writecache_read_hits ) ) ;
DEBUG ( 3 , ( " WRITECACHE: Flushes SEEK=%d, READ=%d, WRITE=%d, READRAW=%d, OPLOCK=%d, CLOSE=%d, SYNC=%d \n " ,
profile_p - > writecache_flushed_writes [ SEEK_FLUSH ] ,
profile_p - > writecache_flushed_writes [ READ_FLUSH ] ,
profile_p - > writecache_flushed_writes [ WRITE_FLUSH ] ,
profile_p - > writecache_flushed_writes [ READRAW_FLUSH ] ,
profile_p - > writecache_flushed_writes [ OPLOCK_RELEASE_FLUSH ] ,
profile_p - > writecache_flushed_writes [ CLOSE_FLUSH ] ,
profile_p - > writecache_flushed_writes [ SYNC_FLUSH ] ) ) ;
}
2000-10-05 22:50:18 +04:00
# endif
1999-12-13 16:27:58 +03:00
2007-10-31 02:22:24 +03:00
if ( wcp & & req - > unread_bytes ) {
/* If we're using receivefile don't
* deal with a write cache .
*/
flush_write_cache ( fsp , WRITE_FLUSH ) ;
delete_write_cache ( fsp ) ;
wcp = NULL ;
}
2002-07-15 14:35:28 +04:00
if ( ! wcp ) {
DO_PROFILE_INC ( writecache_direct_writes ) ;
2007-10-31 02:22:24 +03:00
total_written = real_write_file ( req , fsp , data , pos , n ) ;
2002-07-15 14:35:28 +04:00
return total_written ;
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 9 , ( " write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fsp_name , fsp - > fh - > fd , ( double ) pos , ( unsigned int ) n , ( double ) wcp - > offset , ( unsigned int ) wcp - > data_size ) ) ;
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
fsp - > fh - > pos = pos + n ;
2003-08-15 01:16:06 +04:00
2007-10-31 02:22:24 +03:00
/*
2002-07-15 14:35:28 +04:00
* If we have active cache and it isn ' t contiguous then we flush .
* NOTE : There is a small problem with running out of disk . . . .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( wcp - > data_size ) {
2007-10-19 04:40:25 +04:00
bool cache_flush_needed = False ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( ( pos > = wcp - > offset ) & & ( pos < = wcp - > offset + wcp - > data_size ) ) {
1999-12-13 16:27:58 +03:00
2002-10-03 23:05:36 +04:00
/* ASCII art.... JRA.
+ - - - - - - - - - - - - - - + - - - - -
| Cached data | Rest of allocated cache buffer . . . .
+ - - - - - - - - - - - - - - + - - - - -
+ - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - +
*/
2002-07-15 14:35:28 +04:00
/*
* Start of write overlaps or abutts the existing data .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
size_t data_used = MIN ( ( wcp - > alloc_size - ( pos - wcp - > offset ) ) , n ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
memcpy ( wcp - > data + ( pos - wcp - > offset ) , data , data_used ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the current buffer size with the new data .
*/
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( pos + data_used > wcp - > offset + wcp - > data_size ) {
2002-07-15 14:35:28 +04:00
wcp - > data_size = pos + data_used - wcp - > offset ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the file size if changed .
*/
2002-01-20 03:43:28 +03:00
2002-12-04 06:12:09 +03:00
if ( wcp - > offset + wcp - > data_size > wcp - > file_size ) {
2005-05-09 03:16:28 +04:00
if ( wcp_file_size_change ( fsp ) = = - 1 ) {
return - 1 ;
}
2002-12-04 06:12:09 +03:00
}
2002-01-20 03:43:28 +03:00
2002-07-15 14:35:28 +04:00
/*
* If we used all the data then
* return here .
*/
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( n = = data_used ) {
2002-07-15 14:35:28 +04:00
return n ;
2005-05-09 03:16:28 +04:00
} else {
2002-07-15 14:35:28 +04:00
cache_flush_needed = True ;
2005-05-09 03:16:28 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* Move the start of data forward by the amount used ,
* cut down the amount left by the same amount .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
data + = data_used ;
pos + = data_used ;
n - = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_abutted_writes ) ;
total_written = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
write_path = 1 ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
} else if ( ( pos < wcp - > offset ) & & ( pos + n > wcp - > offset ) & &
( pos + n < = wcp - > offset + wcp - > alloc_size ) ) {
1999-12-13 16:27:58 +03:00
2002-10-03 23:05:36 +04:00
/* ASCII art.... JRA.
+ - - - - - - - - - - - - - - - +
| Cache buffer |
+ - - - - - - - - - - - - - - - +
+ - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - +
*/
2002-07-15 14:35:28 +04:00
/*
* End of write overlaps the existing data .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
size_t data_used = pos + n - wcp - > offset ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
memcpy ( wcp - > data , data + n - data_used , data_used ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the current buffer size with the new data .
*/
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( pos + n > wcp - > offset + wcp - > data_size ) {
2002-07-15 14:35:28 +04:00
wcp - > data_size = pos + n - wcp - > offset ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the file size if changed .
*/
2002-01-20 03:43:28 +03:00
2002-12-04 06:12:09 +03:00
if ( wcp - > offset + wcp - > data_size > wcp - > file_size ) {
2005-05-09 03:16:28 +04:00
if ( wcp_file_size_change ( fsp ) = = - 1 ) {
return - 1 ;
}
2002-12-04 06:12:09 +03:00
}
2002-01-20 03:43:28 +03:00
2002-07-15 14:35:28 +04:00
/*
* We don ' t need to move the start of data , but we
* cut down the amount left by the amount used .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
n - = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* We cannot have used all the data here .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
cache_flush_needed = True ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_abutted_writes ) ;
total_written = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
write_path = 2 ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
} else if ( ( pos > = wcp - > file_size ) & &
( wcp - > offset + wcp - > data_size = = wcp - > file_size ) & &
( pos > wcp - > offset + wcp - > data_size ) & &
( pos < wcp - > offset + wcp - > alloc_size ) ) {
1999-12-13 16:27:58 +03:00
2002-10-03 23:05:36 +04:00
/* ASCII art.... JRA.
End of file - - - - > |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Cached data | Cache buffer |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
+ - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - +
*/
2002-07-15 14:35:28 +04:00
/*
* Non - contiguous write part of which fits within
* the cache buffer and is extending the file
* and the cache contents reflect the current
* data up to the current end of the file .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
size_t data_used ;
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( pos + n < = wcp - > offset + wcp - > alloc_size ) {
2002-07-15 14:35:28 +04:00
data_used = n ;
2005-05-09 03:16:28 +04:00
} else {
2002-07-15 14:35:28 +04:00
data_used = wcp - > offset + wcp - > alloc_size - pos ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Fill in the non - continuous area with zeros .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
memset ( wcp - > data + wcp - > data_size , ' \0 ' ,
pos - ( wcp - > offset + wcp - > data_size ) ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
memcpy ( wcp - > data + ( pos - wcp - > offset ) , data , data_used ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the current buffer size with the new data .
*/
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( pos + data_used > wcp - > offset + wcp - > data_size ) {
2002-07-15 14:35:28 +04:00
wcp - > data_size = pos + data_used - wcp - > offset ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Update the file size if changed .
*/
1999-12-13 16:27:58 +03:00
2002-12-04 06:12:09 +03:00
if ( wcp - > offset + wcp - > data_size > wcp - > file_size ) {
2005-05-09 03:16:28 +04:00
if ( wcp_file_size_change ( fsp ) = = - 1 ) {
return - 1 ;
}
2002-12-04 06:12:09 +03:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* If we used all the data then
* return here .
*/
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( n = = data_used ) {
2002-07-15 14:35:28 +04:00
return n ;
2005-05-09 03:16:28 +04:00
} else {
2002-07-15 14:35:28 +04:00
cache_flush_needed = True ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Move the start of data forward by the amount used ,
* cut down the amount left by the same amount .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
data + = data_used ;
pos + = data_used ;
n - = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_abutted_writes ) ;
total_written = data_used ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
write_path = 3 ;
1999-12-13 16:27:58 +03:00
2007-08-03 20:51:43 +04:00
} else if ( ( pos > = wcp - > file_size ) & &
2005-05-24 08:55:18 +04:00
( n = = 1 ) & &
2007-08-03 20:51:43 +04:00
( wcp - > file_size = = wcp - > offset + wcp - > data_size ) & &
( pos < wcp - > file_size + wcp - > alloc_size ) ) {
2005-05-24 08:55:18 +04:00
/*
2007-08-03 20:51:43 +04:00
End of file - - - - > |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Cached data | Cache buffer |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| < - - - - - - - allocated size - - - - - - - - - - - - - - - - > |
2005-05-24 08:55:18 +04:00
+ - - - - - - - - +
| 1 Byte |
+ - - - - - - - - +
MS - Office seems to do this a lot to determine if there ' s enough
space on the filesystem to write a new file .
2007-08-03 20:51:43 +04:00
Change to :
End of file - - - - > |
+ - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - +
| Zeroed Cached data | 1 Byte |
+ - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - +
*/
2005-05-24 08:55:18 +04:00
flush_write_cache ( fsp , WRITE_FLUSH ) ;
2007-08-03 20:51:43 +04:00
wcp - > offset = wcp - > file_size ;
wcp - > data_size = pos - wcp - > file_size + 1 ;
2005-05-24 08:55:18 +04:00
memset ( wcp - > data , ' \0 ' , wcp - > data_size ) ;
memcpy ( wcp - > data + wcp - > data_size - 1 , data , 1 ) ;
/*
* Update the file size if changed .
*/
if ( wcp - > offset + wcp - > data_size > wcp - > file_size ) {
if ( wcp_file_size_change ( fsp ) = = - 1 ) {
return - 1 ;
}
}
return n ;
2002-07-15 14:35:28 +04:00
} else {
1999-12-13 16:27:58 +03:00
2002-10-03 23:05:36 +04:00
/* ASCII art..... JRA.
Case 1 ) .
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Cached data | Cache buffer |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
+ - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - +
Case 2 ) .
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Cached data | Cache buffer |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
+ - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - +
Case 3 ) .
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
| Cached data | Cache buffer |
+ - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - +
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Data to write |
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
*/
/*
2002-07-15 14:35:28 +04:00
* Write is bigger than buffer , or there is no overlap on the
* low or high ends .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 9 , ( " write_file: non cacheable write : fd = %d, pos = %.0f, len = %u, current cache pos = %.0f \
2005-07-08 08:51:27 +04:00
len = % u \ n " ,fsp->fh->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size ));
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* If write would fit in the cache , and is larger than
* the data already in the cache , flush the cache and
* preferentially copy the data new data into it . Otherwise
* just write the data directly .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( n < = wcp - > alloc_size & & n > wcp - > data_size ) {
cache_flush_needed = True ;
} else {
2007-10-31 02:22:24 +03:00
ssize_t ret = real_write_file ( NULL , fsp , data , pos , n ) ;
2002-01-20 03:43:28 +03:00
2002-10-03 22:10:59 +04:00
/*
* If the write overlaps the entire cache , then
* discard the current contents of the cache .
* Fix from Rasmus Borup Hansen rbh @ math . ku . dk .
*/
if ( ( pos < = wcp - > offset ) & &
( pos + n > = wcp - > offset + wcp - > data_size ) ) {
DEBUG ( 9 , ( " write_file: discarding overwritten write \
2005-07-08 08:51:27 +04:00
cache : fd = % d , off = % .0f , size = % u \ n " , fsp->fh->fd, (double)wcp->offset, (unsigned int)wcp->data_size ));
2002-10-03 22:10:59 +04:00
wcp - > data_size = 0 ;
}
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_direct_writes ) ;
2005-05-09 03:16:28 +04:00
if ( ret = = - 1 ) {
2002-07-15 14:35:28 +04:00
return ret ;
2005-05-09 03:16:28 +04:00
}
2002-01-20 03:43:28 +03:00
2002-12-04 06:12:09 +03:00
if ( pos + ret > wcp - > file_size ) {
wcp - > file_size = pos + ret ;
}
2002-01-20 03:43:28 +03:00
2002-07-15 14:35:28 +04:00
return ret ;
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
write_path = 4 ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( cache_flush_needed ) {
DEBUG ( 3 , ( " WRITE_FLUSH:%d: due to noncontinuous write: fd = %d, size = %.0f, pos = %.0f, \
1999-12-13 16:27:58 +03:00
n = % u , wcp - > offset = % .0f , wcp - > data_size = % u \ n " ,
2005-07-08 08:51:27 +04:00
write_path , fsp - > fh - > fd , ( double ) wcp - > file_size , ( double ) pos , ( unsigned int ) n ,
2002-07-15 14:35:28 +04:00
( double ) wcp - > offset , ( unsigned int ) wcp - > data_size ) ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
flush_write_cache ( fsp , WRITE_FLUSH ) ;
}
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* If the write request is bigger than the cache
* size , write it all out .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( n > wcp - > alloc_size ) {
2007-10-31 02:22:24 +03:00
ssize_t ret = real_write_file ( NULL , fsp , data , pos , n ) ;
2005-05-09 03:16:28 +04:00
if ( ret = = - 1 ) {
2002-07-15 14:35:28 +04:00
return - 1 ;
2005-05-09 03:16:28 +04:00
}
2002-01-20 03:43:28 +03:00
2002-12-04 06:12:09 +03:00
if ( pos + ret > wcp - > file_size ) {
wcp - > file_size = pos + n ;
}
2002-01-20 03:43:28 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_direct_writes ) ;
return total_written + n ;
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* If there ' s any data left , cache it .
*/
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( n ) {
2000-10-05 22:50:18 +04:00
# ifdef WITH_PROFILE
2002-07-15 14:35:28 +04:00
if ( wcp - > data_size ) {
DO_PROFILE_INC ( writecache_abutted_writes ) ;
} else {
DO_PROFILE_INC ( writecache_init_writes ) ;
}
2000-10-05 22:50:18 +04:00
# endif
2002-07-15 14:35:28 +04:00
memcpy ( wcp - > data + wcp - > data_size , data , n ) ;
if ( wcp - > data_size = = 0 ) {
wcp - > offset = pos ;
DO_PROFILE_INC ( writecache_num_write_caches ) ;
}
wcp - > data_size + = n ;
/*
* Update the file size if changed .
*/
2002-12-04 06:12:09 +03:00
if ( wcp - > offset + wcp - > data_size > wcp - > file_size ) {
2005-05-09 03:16:28 +04:00
if ( wcp_file_size_change ( fsp ) = = - 1 ) {
return - 1 ;
}
2002-12-04 06:12:09 +03:00
}
2002-07-15 14:35:28 +04:00
DEBUG ( 9 , ( " wcp->offset = %.0f wcp->data_size = %u cache return %u \n " ,
( double ) wcp - > offset , ( unsigned int ) wcp - > data_size , ( unsigned int ) n ) ) ;
total_written + = n ;
return total_written ; /* .... that's a write :) */
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
return total_written ;
1998-08-17 11:15:54 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Delete the write cache structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 11:40:06 +04:00
1999-12-13 16:27:58 +03:00
void delete_write_cache ( files_struct * fsp )
{
2002-07-15 14:35:28 +04:00
write_cache * wcp ;
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( ! fsp ) {
2002-07-15 14:35:28 +04:00
return ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( ! ( wcp = fsp - > wcp ) ) {
2002-07-15 14:35:28 +04:00
return ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_DEC ( writecache_allocated_write_caches ) ;
allocated_write_caches - - ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
SMB_ASSERT ( wcp - > data_size = = 0 ) ;
2000-10-03 01:03:46 +04:00
2002-07-15 14:35:28 +04:00
SAFE_FREE ( wcp - > data ) ;
SAFE_FREE ( fsp - > wcp ) ;
2000-10-03 01:03:46 +04:00
2002-07-15 14:35:28 +04:00
DEBUG ( 10 , ( " delete_write_cache: File %s deleted write cache \n " , fsp - > fsp_name ) ) ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Setup the write cache structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool setup_write_cache ( files_struct * fsp , SMB_OFF_T file_size )
1999-12-13 16:27:58 +03:00
{
2002-07-15 14:35:28 +04:00
ssize_t alloc_size = lp_write_cache_size ( SNUM ( fsp - > conn ) ) ;
write_cache * wcp ;
2005-05-09 03:16:28 +04:00
if ( allocated_write_caches > = MAX_WRITE_CACHES ) {
2002-07-15 14:35:28 +04:00
return False ;
2005-05-09 03:16:28 +04:00
}
2002-07-15 14:35:28 +04:00
2005-05-09 03:16:28 +04:00
if ( alloc_size = = 0 | | fsp - > wcp ) {
2002-07-15 14:35:28 +04:00
return False ;
2005-05-09 03:16:28 +04:00
}
2002-07-15 14:35:28 +04:00
2004-12-07 21:25:53 +03:00
if ( ( wcp = SMB_MALLOC_P ( write_cache ) ) = = NULL ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 0 , ( " setup_write_cache: malloc fail. \n " ) ) ;
return False ;
}
wcp - > file_size = file_size ;
wcp - > offset = 0 ;
wcp - > alloc_size = alloc_size ;
wcp - > data_size = 0 ;
2005-06-25 00:25:18 +04:00
if ( ( wcp - > data = ( char * ) SMB_MALLOC ( wcp - > alloc_size ) ) = = NULL ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 0 , ( " setup_write_cache: malloc fail for buffer size %u. \n " ,
( unsigned int ) wcp - > alloc_size ) ) ;
SAFE_FREE ( wcp ) ;
return False ;
}
memset ( wcp - > data , ' \0 ' , wcp - > alloc_size ) ;
fsp - > wcp = wcp ;
DO_PROFILE_INC ( writecache_allocated_write_caches ) ;
allocated_write_caches + + ;
2003-11-02 20:10:12 +03:00
DEBUG ( 10 , ( " setup_write_cache: File %s allocated write cache size %lu \n " ,
fsp - > fsp_name , ( unsigned long ) wcp - > alloc_size ) ) ;
2000-10-03 01:03:46 +04:00
2002-07-15 14:35:28 +04:00
return True ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Cope with a size change .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void set_filelen_write_cache ( files_struct * fsp , SMB_OFF_T file_size )
{
2002-07-15 14:35:28 +04:00
if ( fsp - > wcp ) {
/* The cache *must* have been flushed before we do this. */
if ( fsp - > wcp - > data_size ! = 0 ) {
2007-07-09 20:27:13 +04:00
char * msg ;
asprintf ( & msg , " set_filelen_write_cache: size change "
" on file %s with write cache size = %lu \n " ,
fsp - > fsp_name ,
( unsigned long ) fsp - > wcp - > data_size ) ;
2002-07-15 14:35:28 +04:00
smb_panic ( msg ) ;
}
fsp - > wcp - > file_size = file_size ;
}
1999-12-13 16:27:58 +03:00
}
/*******************************************************************
Flush a write cache struct to disk .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t flush_write_cache ( files_struct * fsp , enum flush_reason_enum reason )
{
2002-07-15 14:35:28 +04:00
write_cache * wcp = fsp - > wcp ;
size_t data_size ;
ssize_t ret ;
1999-12-13 16:27:58 +03:00
2005-05-09 03:16:28 +04:00
if ( ! wcp | | ! wcp - > data_size ) {
2002-07-15 14:35:28 +04:00
return 0 ;
2005-05-09 03:16:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
data_size = wcp - > data_size ;
wcp - > data_size = 0 ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DO_PROFILE_DEC_INC ( writecache_num_write_caches , writecache_flushed_writes [ reason ] ) ;
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 9 , ( " flushing write cache: fd = %d, off=%.0f, size=%u \n " ,
2005-07-08 08:51:27 +04:00
fsp - > fh - > fd , ( double ) wcp - > offset , ( unsigned int ) data_size ) ) ;
1999-12-13 16:27:58 +03:00
2000-10-05 22:50:18 +04:00
# ifdef WITH_PROFILE
2005-05-09 03:16:28 +04:00
if ( data_size = = wcp - > alloc_size ) {
2002-07-15 14:35:28 +04:00
DO_PROFILE_INC ( writecache_num_perfect_writes ) ;
2005-05-09 03:16:28 +04:00
}
2000-10-05 22:50:18 +04:00
# endif
1999-12-13 16:27:58 +03:00
2007-10-31 02:22:24 +03:00
ret = real_write_file ( NULL , fsp , wcp - > data , wcp - > offset , data_size ) ;
2002-01-20 03:04:15 +03:00
2002-07-15 14:35:28 +04:00
/*
* Ensure file size if kept up to date if write extends file .
*/
2002-01-20 03:04:15 +03:00
2005-05-09 03:16:28 +04:00
if ( ( ret ! = - 1 ) & & ( wcp - > offset + ret > wcp - > file_size ) ) {
2002-07-15 14:35:28 +04:00
wcp - > file_size = wcp - > offset + ret ;
2005-05-09 03:16:28 +04:00
}
2002-01-20 03:04:15 +03:00
2002-07-15 14:35:28 +04:00
return ret ;
1999-12-13 16:27:58 +03:00
}
2000-02-03 08:17:25 +03: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 ) ) & &
( lp_syncalways ( SNUM ( conn ) ) | | write_through ) ) {
2007-06-15 23:24:04 +04:00
int ret = flush_write_cache ( fsp , SYNC_FLUSH ) ;
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2008-01-07 14:49:02 +03:00
ret = SMB_VFS_FSYNC ( 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
}
2002-03-20 03:46:53 +03:00
/************************************************************
Perform a stat whether a valid fd or not .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int fsp_stat ( files_struct * fsp , SMB_STRUCT_STAT * pst )
{
2005-07-08 08:51:27 +04:00
if ( fsp - > fh - > fd = = - 1 ) {
2003-05-14 14:59:01 +04:00
return SMB_VFS_STAT ( fsp - > conn , fsp - > fsp_name , pst ) ;
2005-05-09 03:16:28 +04:00
} else {
2008-01-07 15:21:26 +03:00
return SMB_VFS_FSTAT ( fsp , pst ) ;
2005-05-09 03:16:28 +04:00
}
2002-03-20 03:46:53 +03:00
}