diff --git a/lib/clean_system.sh b/lib/clean_system.sh index 5297eb9..e2b0080 100644 --- a/lib/clean_system.sh +++ b/lib/clean_system.sh @@ -34,22 +34,30 @@ clean_deep_system() { safe_sudo_find_delete "/var/log" "*.gz" "$MOLE_LOG_AGE_DAYS" "f" log_success "Old system logs (${MOLE_LOG_AGE_DAYS}+ days)" - # Clean Library Updates safely - iterate and delete individual items + # Clean Library Updates safely - skip if SIP is enabled to avoid error messages + # SIP-protected files in /Library/Updates cannot be deleted even with sudo if [[ -d "/Library/Updates" && ! -L "/Library/Updates" ]]; then - local updates_cleaned=0 - while IFS= read -r -d '' item; do - # Skip system-protected files (restricted flag) - local item_flags - item_flags=$(stat -f%Sf "$item" 2> /dev/null || echo "") - if [[ "$item_flags" == *"restricted"* ]]; then - continue - fi + if is_sip_enabled; then + # SIP is enabled, skip /Library/Updates entirely to avoid error messages + # These files are system-protected and cannot be removed + : # No-op, silently skip + else + # SIP is disabled, attempt cleanup with restricted flag check + local updates_cleaned=0 + while IFS= read -r -d '' item; do + # Skip system-protected files (restricted flag) + local item_flags + item_flags=$(stat -f%Sf "$item" 2> /dev/null || echo "") + if [[ "$item_flags" == *"restricted"* ]]; then + continue + fi - if safe_sudo_remove "$item"; then - ((updates_cleaned++)) - fi - done < <(find /Library/Updates -mindepth 1 -maxdepth 1 -print0 2> /dev/null) - [[ $updates_cleaned -gt 0 ]] && log_success "System library updates" + if safe_sudo_remove "$item"; then + ((updates_cleaned++)) + fi + done < <(find /Library/Updates -mindepth 1 -maxdepth 1 -print0 2> /dev/null) + [[ $updates_cleaned -gt 0 ]] && log_success "System library updates" + fi fi # Clean orphaned cask records (delegated to clean_brew module) diff --git a/lib/common.sh b/lib/common.sh index 222737a..8235f6f 100755 --- a/lib/common.sh +++ b/lib/common.sh @@ -58,6 +58,24 @@ declare -a DEFAULT_WHITELIST_PATTERNS=( "$FINDER_METADATA_SENTINEL" ) +# Check if System Integrity Protection is enabled +# Returns: 0 if SIP is enabled, 1 if disabled or cannot determine +is_sip_enabled() { + if ! command -v csrutil > /dev/null 2>&1; then + # If csrutil not available, assume SIP is enabled for safety + return 0 + fi + + local sip_status + sip_status=$(csrutil status 2> /dev/null || echo "") + + if echo "$sip_status" | grep -qi "enabled"; then + return 0 + else + return 1 + fi +} + # Get spinner characters (overridable via MO_SPINNER_CHARS) mo_spinner_chars() { local chars="${MO_SPINNER_CHARS:-|/-\\}" diff --git a/mole b/mole index ab7a44d..35fb51f 100755 --- a/mole +++ b/mole @@ -22,7 +22,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/lib/common.sh" # Version info -VERSION="1.11.5" +VERSION="1.11.6" MOLE_TAGLINE="can dig deep to clean your Mac." # Check if Touch ID is already configured