2026-02-16 09:02:48 +00:00
# define MODULE_LOG_PREFIX "files"
# include "globals.h"
# include "oscam-files.h"
# include "oscam-lock.h"
# include "oscam-string.h"
extern CS_MUTEX_LOCK readdir_lock ;
extern char cs_tmpdir [ 200 ] ;
/* Gets the tmp dir */
char * get_tmp_dir ( void )
{
if ( cs_tmpdir [ 0 ] )
{
return cs_tmpdir ;
}
# if defined(__CYGWIN__)
char * d = getenv ( " TMPDIR " ) ;
if ( ! d | | ! d [ 0 ] )
{
d = getenv ( " TMP " ) ;
}
if ( ! d | | ! d [ 0 ] )
{
d = getenv ( " TEMP " ) ;
}
if ( ! d | | ! d [ 0 ] )
{
getcwd ( cs_tmpdir , sizeof ( cs_tmpdir ) - 1 ) ;
}
cs_strncpy ( cs_tmpdir , d , sizeof ( cs_tmpdir ) ) ;
char * p = cs_tmpdir ;
while ( * p ) { p + + ; }
p - - ;
if ( * p ! = ' / ' & & * p ! = ' \\ ' )
{
cs_strncat ( cs_tmpdir , " / " , sizeof ( cs_tmpdir ) ) ;
}
cs_strncat ( cs_tmpdir , " _oscam " , sizeof ( cs_tmpdir ) ) ;
# else
cs_strncpy ( cs_tmpdir , " /tmp/.oscam " , sizeof ( cs_tmpdir ) ) ;
# endif
mkdir ( cs_tmpdir , S_IRWXU ) ;
return cs_tmpdir ;
}
char * get_tmp_dir_filename ( char * dest , size_t destlen , const char * filename )
{
char * tmp_dir = get_tmp_dir ( ) ;
const char * slash = " / " ;
if ( tmp_dir [ cs_strlen ( tmp_dir ) - 1 ] = = ' / ' )
{
slash = " " ;
}
snprintf ( dest , destlen , " %s%s%s " , tmp_dir , slash , filename ) ;
return dest ;
}
/* Return 1 if the file exists, else 0 */
bool file_exists ( const char * filename )
{
return access ( filename , R_OK ) = = 0 ;
}
/* Finds a file in the system PATH.
Returns a newly allocated string with the full path , or NULL if not found .
Caller must free ( ) the returned string . */
char * find_in_path ( const char * filename )
{
// If filename already has '/', don't search PATH
if ( strchr ( filename , ' / ' ) ) {
return strdup ( filename ) ;
}
char * paths ; const char * path = getenv ( " PATH " ) ; if ( ! path | | ! ( paths = strdup ( path ) ) ) return NULL ;
char * saveptr = NULL ;
char * dir = strtok_r ( paths , " : " , & saveptr ) ;
char fullpath [ PATH_MAX ] ;
char * result = NULL ;
while ( dir ) {
if ( * dir = = ' \0 ' ) dir = " . " ;
snprintf ( fullpath , sizeof ( fullpath ) , " %s/%s " , dir , filename ) ;
if ( file_exists ( fullpath ) ) {
result = strdup ( fullpath ) ;
break ;
}
dir = strtok_r ( NULL , " : " , & saveptr ) ;
}
free ( paths ) ;
return result ;
}
/* Copies a file from srcfile to destfile. If an error occured before writing,
- 1 is returned , else - 2. On success , 0 is returned . */
int32_t file_copy ( char * srcfile , char * destfile )
{
FILE * src , * dest ;
int32_t ch ;
src = fopen ( srcfile , " r " ) ;
if ( ! src )
{
cs_log ( " Error opening file %s for reading (errno=%d %s)! " , srcfile , errno , strerror ( errno ) ) ;
return - 1 ;
}
dest = fopen ( destfile , " w " ) ;
if ( ! dest )
{
cs_log ( " Error opening file %s for writing (errno=%d %s)! " , destfile , errno , strerror ( errno ) ) ;
fclose ( src ) ;
return - 1 ;
}
while ( 1 )
{
ch = fgetc ( src ) ;
if ( ch = = EOF )
{
break ;
}
else
{
fputc ( ch , dest ) ;
if ( ferror ( dest ) )
{
cs_log ( " Error while writing to file %s (errno=%d %s)! " , destfile , errno , strerror ( errno ) ) ;
fclose ( src ) ;
fclose ( dest ) ;
return - 2 ;
}
}
}
fclose ( src ) ;
fclose ( dest ) ;
return ( 0 ) ;
}
/* Overwrites destfile with temp_file. If forceBakOverWrite = 0,
the bakfile will not be overwritten if it exists , else it will be . */
int32_t safe_overwrite_with_bak ( char * destfile , char * temp_file , char * bakfile , int32_t forceBakOverWrite )
{
int32_t rc ;
if ( file_exists ( destfile ) )
{
if ( forceBakOverWrite ! = 0 | | ! file_exists ( bakfile ) )
{
if ( file_copy ( destfile , bakfile ) < 0 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " Error copying original config file %s to %s. The original config will be left untouched! " , destfile , bakfile ) ;
2026-02-16 09:02:48 +00:00
if ( unlink ( temp_file ) < 0 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " Error removing temp config file %s (errno=%d %s)! " , temp_file , errno , strerror ( errno ) ) ;
2026-02-16 09:02:48 +00:00
}
return 1 ;
}
}
}
rc = file_copy ( temp_file , destfile ) ;
if ( rc < 0 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " An error occured while writing the new config file %s. " , destfile ) ;
2026-02-16 09:02:48 +00:00
if ( rc = = - 2 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " The config will be missing or only partly filled upon next startup as this is a non-recoverable error! Please restore from backup or try again. " ) ;
2026-02-16 09:02:48 +00:00
}
if ( unlink ( temp_file ) < 0 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " Error removing temp config file %s (errno=%d %s)! " , temp_file , errno , strerror ( errno ) ) ;
2026-02-16 09:02:48 +00:00
}
return 1 ;
}
if ( unlink ( temp_file ) < 0 )
{
2026-02-23 16:40:08 +00:00
cs_log ( " Error removing temp config file %s (errno=%d %s)! " , temp_file , errno , strerror ( errno ) ) ;
2026-02-16 09:02:48 +00:00
}
return 0 ;
}
# ifdef MODULE_GBOX
char * get_gbox_filename ( char * dest , size_t destlen , const char * filename )
{
char * tmp_dir = get_tmp_dir ( ) ;
const char * slash = " / " ;
if ( cfg . gbox_tmp_dir ! = NULL )
{
if ( cfg . gbox_tmp_dir [ cs_strlen ( cfg . gbox_tmp_dir ) - 1 ] = = ' / ' )
{
slash = " " ;
}
snprintf ( dest , destlen , " %s%s%s " , cfg . gbox_tmp_dir , slash , filename ) ;
}
else
{
if ( tmp_dir [ cs_strlen ( tmp_dir ) - 1 ] = = ' / ' ) { slash = " " ; }
snprintf ( dest , destlen , " %s%s%s " , tmp_dir , slash , filename ) ;
}
return dest ;
}
# endif