@ -14,6 +14,7 @@
# include <errno.h>
# include <env_flags.h>
# include <fcntl.h>
# include <libgen.h>
# include <linux/fs.h>
# include <linux/stringify.h>
# include <ctype.h>
@ -1225,9 +1226,48 @@ static int flash_read(int fd)
return 0 ;
}
static int flash_open_tempfile ( const char * * dname , const char * * target_temp )
{
char * dup_name = strdup ( DEVNAME ( dev_current ) ) ;
char * temp_name = NULL ;
int rc = - 1 ;
if ( ! dup_name )
return - 1 ;
* dname = dirname ( dup_name ) ;
if ( ! * dname )
goto err ;
rc = asprintf ( & temp_name , " %s/XXXXXX " , * dname ) ;
if ( rc = = - 1 )
goto err ;
rc = mkstemp ( temp_name ) ;
if ( rc = = - 1 ) {
/* fall back to in place write */
fprintf ( stderr ,
" Can't create %s: %s \n " , temp_name , strerror ( errno ) ) ;
free ( temp_name ) ;
} else {
* target_temp = temp_name ;
/* deliberately leak dup_name as dname /might/ point into
* it and we need it for our caller
*/
dup_name = NULL ;
}
err :
if ( dup_name )
free ( dup_name ) ;
return rc ;
}
static int flash_io_write ( int fd_current )
{
int fd_target , rc , dev_target ;
int fd_target = - 1 , rc , dev_target ;
const char * dname , * target_temp = NULL ;
if ( have_redund_env ) {
/* switch to next partition for writing */
@ -1242,8 +1282,17 @@ static int flash_io_write(int fd_current)
goto exit ;
}
} else {
struct stat sb ;
if ( fstat ( fd_current , & sb ) = = 0 & & S_ISREG ( sb . st_mode ) ) {
/* if any part of flash_open_tempfile() fails we fall
* back to in - place writes
*/
fd_target = flash_open_tempfile ( & dname , & target_temp ) ;
}
dev_target = dev_current ;
fd_target = fd_current ;
if ( fd_target = = - 1 )
fd_target = fd_current ;
}
rc = flash_write ( fd_current , fd_target , dev_target ) ;
@ -1254,7 +1303,7 @@ static int flash_io_write(int fd_current)
DEVNAME ( dev_current ) , strerror ( errno ) ) ;
}
if ( have_redund_env ) {
if ( fd_current ! = fd_target ) {
if ( fsync ( fd_target ) & &
! ( errno = = EINVAL | | errno = = EROFS ) ) {
fprintf ( stderr ,
@ -1268,6 +1317,34 @@ static int flash_io_write(int fd_current)
DEVNAME ( dev_target ) , strerror ( errno ) ) ;
rc = - 1 ;
}
if ( target_temp ) {
int dir_fd ;
dir_fd = open ( dname , O_DIRECTORY | O_RDONLY ) ;
if ( dir_fd = = - 1 )
fprintf ( stderr ,
" Can't open %s: %s \n " ,
dname , strerror ( errno ) ) ;
if ( rename ( target_temp , DEVNAME ( dev_target ) ) ) {
fprintf ( stderr ,
" rename failed %s => %s: %s \n " ,
target_temp , DEVNAME ( dev_target ) ,
strerror ( errno ) ) ;
rc = - 1 ;
}
if ( dir_fd ! = - 1 & & fsync ( dir_fd ) )
fprintf ( stderr ,
" fsync failed on %s: %s \n " ,
dname , strerror ( errno ) ) ;
if ( dir_fd ! = - 1 & & close ( dir_fd ) )
fprintf ( stderr ,
" I/O error on %s: %s \n " ,
dname , strerror ( errno ) ) ;
}
}
exit :
return rc ;