diff --git a/cmd/analyze/scanner.go b/cmd/analyze/scanner.go index ae5ab3f..2f0f797 100644 --- a/cmd/analyze/scanner.go +++ b/cmd/analyze/scanner.go @@ -471,11 +471,13 @@ func calculateDirSizeConcurrent(root string, largeFileChan chan<- fileEntry, duS defer func() { <-duSem }() return getDirectorySizeFromDu(path) }() - if err == nil && size > 0 { - atomic.AddInt64(&total, size) + if err != nil || size <= 0 { + size = calculateDirSizeFast(path, filesScanned, dirsScanned, bytesScanned, currentPath) + } else { atomic.AddInt64(bytesScanned, size) - atomic.AddInt64(dirsScanned, 1) } + atomic.AddInt64(&total, size) + atomic.AddInt64(dirsScanned, 1) }(fullPath) continue } diff --git a/install.sh b/install.sh index 8a45c84..b7d05be 100755 --- a/install.sh +++ b/install.sh @@ -52,6 +52,39 @@ log_error() { echo -e "${YELLOW}${ICON_ERROR}${NC} $1"; } log_admin() { [[ ${VERBOSE} -eq 1 ]] && echo -e "${BLUE}${ICON_ADMIN}${NC} $1"; } log_confirm() { [[ ${VERBOSE} -eq 1 ]] && echo -e "${BLUE}${ICON_CONFIRM}${NC} $1"; } +safe_rm() { + local target="${1:-}" + local tmp_root + + if [[ -z "$target" ]]; then + log_error "safe_rm: empty path" + return 1 + fi + if [[ ! -e "$target" ]]; then + return 0 + fi + + tmp_root="${TMPDIR:-/tmp}" + case "$target" in + "$tmp_root" | /tmp) + log_error "safe_rm: refusing to remove temp root: $target" + return 1 + ;; + "$tmp_root"/* | /tmp/*) ;; + *) + log_error "safe_rm: refusing to remove non-temp path: $target" + return 1 + ;; + esac + + if [[ -d "$target" ]]; then + find "$target" -depth \( -type f -o -type l \) -exec rm -f {} + 2> /dev/null || true + find "$target" -depth -type d -exec rmdir {} + 2> /dev/null || true + else + rm -f "$target" 2> /dev/null || true + fi +} + # Install defaults INSTALL_DIR="/usr/local/bin" CONFIG_DIR="$HOME/.config/mole" @@ -100,7 +133,16 @@ resolve_source_dir() { local tmp tmp="$(mktemp -d)" - trap "stop_line_spinner 2>/dev/null; rm -rf \"$tmp\"" EXIT + + # Safe cleanup function for temporary directory + cleanup_tmp() { + stop_line_spinner 2> /dev/null || true + if [[ -z "${tmp:-}" ]]; then + return 0 + fi + safe_rm "$tmp" + } + trap cleanup_tmp EXIT local branch="${MOLE_VERSION:-}" if [[ -z "$branch" ]]; then diff --git a/lib/core/base.sh b/lib/core/base.sh index 95b3ae4..ce131ca 100644 --- a/lib/core/base.sh +++ b/lib/core/base.sh @@ -539,9 +539,14 @@ register_temp_dir() { mktemp_file() { local prefix="${1:-mole}" local temp + local error_msg # Use TMPDIR if set, otherwise /tmp # Add .XXXXXX suffix to work with both BSD and GNU mktemp - temp=$(mktemp "${TMPDIR:-/tmp}/${prefix}.XXXXXX") || return 1 + if ! error_msg=$(mktemp "${TMPDIR:-/tmp}/${prefix}.XXXXXX" 2>&1); then + echo "Error: Failed to create temporary file: $error_msg" >&2 + return 1 + fi + temp="$error_msg" register_temp_file "$temp" echo "$temp" } diff --git a/lib/core/common.sh b/lib/core/common.sh index 923122a..2408294 100755 --- a/lib/core/common.sh +++ b/lib/core/common.sh @@ -34,7 +34,7 @@ update_via_homebrew() { temp_upgrade=$(mktemp_file "brew_upgrade") # Set up trap for interruption (Ctrl+C) with inline cleanup - trap "stop_inline_spinner 2>/dev/null; rm -f \"$temp_update\" \"$temp_upgrade\" 2>/dev/null; echo \"\"; exit 130" INT TERM + trap 'stop_inline_spinner 2>/dev/null; safe_remove "$temp_update" true; safe_remove "$temp_upgrade" true; echo ""; exit 130' INT TERM # Update Homebrew if [[ -t 1 ]]; then @@ -73,7 +73,8 @@ update_via_homebrew() { trap - INT TERM # Cleanup temp files - rm -f "$temp_update" "$temp_upgrade" + safe_remove "$temp_update" true + safe_remove "$temp_upgrade" true if echo "$upgrade_output" | grep -q "already installed"; then local installed_version