@@ -2775,6 +2775,60 @@ static PromiseResult VerifyFileAttributes(EvalContext *ctx, const char *file, co
27752775 return result ;
27762776}
27772777
2778+ bool HandleFileObstruction (EvalContext * ctx , const char * path , const struct stat * sb , const Attributes * attr , const Promise * pp , PromiseResult * result )
2779+ {
2780+ if (!sb )
2781+ {
2782+ return true;
2783+ }
2784+ if (!attr )
2785+ {
2786+ return false;
2787+ }
2788+
2789+ // Use local variables to help static analysis tools understand that
2790+ // the pointers have been checked for NULL before dereferencing
2791+ const struct stat * const safe_sb = sb ; // Explicit alias after null check
2792+ const Attributes * const safe_attr = attr ; // Explicit alias after null check
2793+
2794+ const mode_t st_mode = safe_sb -> st_mode ;
2795+ const bool move_obstructions = safe_attr -> move_obstructions ;
2796+
2797+ // If path exists, but is not a regular file, it's an obstruction
2798+ if (!S_ISREG (st_mode ))
2799+ {
2800+ if (move_obstructions )
2801+ {
2802+ if (MakingChanges (ctx , pp , safe_attr , result , "move obstruction '%s'" , path ))
2803+ {
2804+ char backup [CF_BUFSIZE ];
2805+ snprintf (backup , sizeof (backup ), "%s.cf-moved" , path );
2806+
2807+ if (rename (path , backup ) == -1 )
2808+ {
2809+ RecordFailure (ctx , pp , safe_attr , "Could not move obstruction '%s' to '%s'. (rename: %s)" ,
2810+ path , backup , GetErrorStr ());
2811+ * result = PromiseResultUpdate (* result , PROMISE_RESULT_FAIL );
2812+ return false;
2813+ }
2814+ else
2815+ {
2816+ RecordChange (ctx , pp , safe_attr , "Moved obstructing path '%s' to '%s'" , path , backup );
2817+ * result = PromiseResultUpdate (* result , PROMISE_RESULT_CHANGE );
2818+ return true;
2819+ }
2820+ }
2821+ }
2822+ else if (!S_ISLNK (st_mode ))
2823+ {
2824+ RecordFailure (ctx , pp , safe_attr , "Path '%s' is not a regular file and move_obstructions is not set" , path );
2825+ * result = PromiseResultUpdate (* result , PROMISE_RESULT_FAIL );
2826+ return false;
2827+ }
2828+ }
2829+ return true;
2830+ }
2831+
27782832bool DepthSearch (EvalContext * ctx , char * name , const struct stat * sb , int rlevel , const Attributes * attr ,
27792833 const Promise * pp , dev_t rootdevice , PromiseResult * result )
27802834{
@@ -2798,7 +2852,7 @@ bool DepthSearch(EvalContext *ctx, char *name, const struct stat *sb, int rlevel
27982852 {
27992853 Log (LOG_LEVEL_ERR , "Failed to chdir into '%s'. (chdir: '%s')" , basedir , GetErrorStr ());
28002854 return false;
2801- }
2855+ }
28022856 if (!attr -> haveselect || SelectLeaf (ctx , name , sb , & (attr -> select )))
28032857 {
28042858 /* Renames are handled separately. */
0 commit comments