Added testfile probe to check if destination directory is writable

This commit is contained in:
Fabian Druschke
2025-12-09 16:19:32 +01:00
parent 26e5cb9894
commit c235349288

View File

@@ -77,9 +77,6 @@
#endif
#endif
#define NWIPE_PDF_DIR_MODE ( S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH )
/* -> 0755: rwx for owner, r-x for group and others */
int terminate_signal;
int user_abort;
int global_wipe_status;
@@ -99,11 +96,62 @@ int devnamecmp( const void* a, const void* b )
return ( ret );
}
static int nwipe_ensure_directory( const char* path )
#define NWIPE_PDF_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
/* -> 0755: rwx for owner, r-x for group and others */
/* Helper: try to create and remove a temporary file inside the directory.
* This catches cases where access(path, W_OK) passes (especially as root)
* but the underlying filesystem does not allow creating regular files,
* e.g. /proc or other pseudo/readonly filesystems.
*/
static int nwipe_probe_directory_writable( const char *path )
{
const char *suffix = "/.nwipe_pdf_testXXXXXX";
size_t path_len = strlen( path );
size_t suffix_len = strlen( suffix );
size_t total_len = path_len + suffix_len + 1; /* +1 for '\0' */
char *tmpl = (char *)malloc( total_len );
if( tmpl == NULL )
{
nwipe_log( NWIPE_LOG_ERROR,
"Failed to allocate memory to probe PDFreportpath '%s'.",
path );
return -1;
}
/* Build template "<path>/.nwipe_pdf_testXXXXXX" */
snprintf( tmpl, total_len, "%s%s", path, suffix );
int fd = mkstemp( tmpl );
if( fd < 0 )
{
nwipe_log( NWIPE_LOG_ERROR,
"PDFreportpath '%s' is not writable (cannot create test file): %s.",
path, strerror( errno ) );
free( tmpl );
return -1;
}
/* Successfully created a temporary file, now clean it up. */
close( fd );
if( unlink( tmpl ) != 0 )
{
/* Not fatal for our check, but log it anyway. */
nwipe_log( NWIPE_LOG_WARNING,
"Failed to remove temporary test file '%s' in PDFreportpath '%s': %s.",
tmpl, path, strerror( errno ) );
}
free( tmpl );
return 0;
}
static int nwipe_ensure_directory( const char *path )
{
struct stat st;
char* tmp;
char* p;
char *tmp;
char *p;
size_t len;
if( path == NULL || path[0] == '\0' )
@@ -112,32 +160,23 @@ static int nwipe_ensure_directory( const char* path )
return 0;
}
/* Special case: current directory.
* Historically nwipe called access(".", W_OK), so we keep that behavior. */
if( strcmp( path, "." ) == 0 )
{
if( access( path, W_OK ) != 0 )
{
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath '%s' is not writable: %s.", path, strerror( errno ) );
return -1;
}
return 0;
}
/* 1. First try: does the path already exist? */
if( stat( path, &st ) == 0 )
{
/* Path exists; make sure it's a directory. */
if( !S_ISDIR( st.st_mode ) )
{
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath '%s' exists but is not a directory.", path );
nwipe_log( NWIPE_LOG_ERROR,
"PDFreportpath '%s' exists but is not a directory.",
path );
return -1;
}
/* Check that we can write into it. */
if( access( path, W_OK ) != 0 )
/* Even if access() says it's writable (especially as root),
* we still probe by actually creating a test file. */
if( nwipe_probe_directory_writable( path ) != 0 )
{
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath '%s' is not writable: %s.", path, strerror( errno ) );
/* Detailed error already logged. */
return -1;
}
@@ -148,17 +187,21 @@ static int nwipe_ensure_directory( const char* path )
/* stat() failed: if this is not "does not exist", propagate the error. */
if( errno != ENOENT )
{
nwipe_log( NWIPE_LOG_ERROR, "Failed to stat PDFreportpath '%s': %s.", path, strerror( errno ) );
nwipe_log( NWIPE_LOG_ERROR,
"Failed to stat PDFreportpath '%s': %s.",
path, strerror( errno ) );
return -1;
}
/* 2. Directory does not exist -> create it recursively (mkdir -p style). */
len = strlen( path );
tmp = (char*) malloc( len + 1 );
tmp = (char *)malloc( len + 1 );
if( tmp == NULL )
{
nwipe_log( NWIPE_LOG_ERROR, "Failed to allocate memory to create PDFreportpath '%s'.", path );
nwipe_log( NWIPE_LOG_ERROR,
"Failed to allocate memory to create PDFreportpath '%s'.",
path );
return -1;
}
@@ -186,9 +229,7 @@ static int nwipe_ensure_directory( const char* path )
{
nwipe_log( NWIPE_LOG_ERROR,
"Failed to create directory '%s' for PDFreportpath '%s': %s.",
tmp,
path,
strerror( errno ) );
tmp, path, strerror( errno ) );
free( tmp );
return -1;
}
@@ -203,25 +244,17 @@ static int nwipe_ensure_directory( const char* path )
{
nwipe_log( NWIPE_LOG_ERROR,
"Failed to create directory '%s' for PDFreportpath '%s': %s.",
tmp,
path,
strerror( errno ) );
tmp, path, strerror( errno ) );
free( tmp );
return -1;
return -1;
}
free( tmp );
/* 3. Final sanity check: ensure the path now exists, is a directory and writable. */
if( stat( path, &st ) != 0 || !S_ISDIR( st.st_mode ) )
/* 3. Final sanity check: ensure the path is writable by probing with a file. */
if( nwipe_probe_directory_writable( path ) != 0 )
{
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath '%s' could not be verified as a directory after creation.", path );
return -1;
}
if( access( path, W_OK ) != 0 )
{
nwipe_log( NWIPE_LOG_ERROR, "PDFreportpath '%s' is not writable after creation: %s.", path, strerror( errno ) );
/* Detailed error already logged. */
return -1;
}