#!/usr/bin/env bash
# Exercise 2: audit a directory tree for risky files and disk hogs (medium)
# Run with: bash linux_filesystem_and_permissions_exercise_2.sh
#
# The self-check builds a throwaway tree in a temp directory and calls your
# functions on it. Use `find` (portable flags only: -type, -perm, -size, -name,
# -newer, -print) and `wc`/`du`/`sort`. Print paths RELATIVE to the root you
# were given (strip the "ROOT/" prefix), sorted alphabetically.
#
# STEP 1: world_writable ROOT  — regular files writable by "others"
# STEP 2: setuid_files ROOT    — regular files with the setuid bit
# STEP 3: secrets_exposed ROOT — files named *.env or *.pem that are readable by
#                                group or others (any of g+r, o+r)
# STEP 4: largest_files ROOT N — the N largest regular files, biggest first,
#                                as "SIZE_IN_KB PATH" (use du -k; ties don't occur)
# STEP 5: fix_secrets ROOT     — chmod every file found in step 3 to 600
#                                (then secrets_exposed must print nothing)

set -uo pipefail

world_writable() {
  local root="$1"
  # TODO
  : "$root"
}

setuid_files() {
  local root="$1"
  # TODO
  : "$root"
}

secrets_exposed() {
  local root="$1"
  # TODO
  : "$root"
}

largest_files() {
  local root="$1" n="$2"
  # TODO
  : "$root" "$n"
}

fix_secrets() {
  local root="$1"
  # TODO
  : "$root"
}

# --- self-check: do not modify below this line ---
all_ok=true
check() {
  if [[ "$2" == "$3" ]]; then echo "ok   $1"; else echo "FAIL $1"; echo "     got:      $(printf '%s' "$2" | tr '\n' '|')"; echo "     expected: $(printf '%s' "$3" | tr '\n' '|')"; all_ok=false; fi
}

ROOT="$(mktemp -d)"
trap 'rm -rf "$ROOT"' EXIT
mkdir -p "$ROOT/app/config" "$ROOT/app/bin" "$ROOT/tmp" "$ROOT/logs"
echo "DB_PASSWORD=x" > "$ROOT/app/config/prod.env";  chmod 644 "$ROOT/app/config/prod.env"
echo "KEY" > "$ROOT/app/config/tls.pem";             chmod 640 "$ROOT/app/config/tls.pem"
echo "ok" > "$ROOT/app/config/dev.env";              chmod 600 "$ROOT/app/config/dev.env"
echo "#!/bin/sh" > "$ROOT/app/bin/helper";           chmod 4755 "$ROOT/app/bin/helper"
echo "#!/bin/sh" > "$ROOT/app/bin/run";              chmod 755 "$ROOT/app/bin/run"
echo "scratch" > "$ROOT/tmp/shared.txt";             chmod 666 "$ROOT/tmp/shared.txt"
echo "notes" > "$ROOT/tmp/notes.txt";                chmod 602 "$ROOT/tmp/notes.txt"
dd if=/dev/zero of="$ROOT/logs/big.log" bs=1024 count=300 2>/dev/null
dd if=/dev/zero of="$ROOT/logs/mid.log" bs=1024 count=120 2>/dev/null
dd if=/dev/zero of="$ROOT/logs/small.log" bs=1024 count=40 2>/dev/null

check "world_writable"  "$(world_writable "$ROOT")"  "$(printf 'tmp/notes.txt\ntmp/shared.txt')"
check "setuid_files"    "$(setuid_files "$ROOT")"    "app/bin/helper"
check "secrets_exposed" "$(secrets_exposed "$ROOT")" "$(printf 'app/config/prod.env\napp/config/tls.pem')"
got="$(largest_files "$ROOT" 2)"
check "largest_files order" "$(printf '%s\n' "$got" | awk '{print $2}')" "$(printf 'logs/big.log\nlogs/mid.log')"
check "largest_files size"  "$(printf '%s\n' "$got" | awk 'NR==1{print ($1>=300 && $1<=320) ? "ok" : $1}')" "ok"
fix_secrets "$ROOT"
check "fix_secrets"     "$(secrets_exposed "$ROOT")" ""
check "fix_secrets mode" "$(ls -l "$ROOT/app/config/prod.env" | cut -c1-10)" "-rw-------"

if $all_ok; then echo "PASS"; else echo "FAIL"; fi
