#!/bin/busybox ash # (c) Robert Shingledecker 2009, 2010 . /etc/init.d/tc-functions useBusybox getMirror KERNELVER=$(uname -r) TCE_DB="tce.db" TCE_LST="tce.lst" AUDIT_RESULTS="/tmp/audit_results.txt" AUDIT_WORK="/tmp/audit_work.txt" AUDIT_MARKED="/tmp/audit_marked.lst" DEFAULT_DIR=/etc/sysconfig/tcedir/optional ACTION="$1" ARG2="$2" abort(){ echo "Usage: tce-audit { updatedeps | builddb | auditall | fetchmissing | nodepends | notrequired | marked | clearlst } /path/to/tcedir/" echo " tce-audit { dependson | requiredby | audit | delete } /path/to/tcedir/extension.tcz" echo " tce-audit { remove }" exit 1 } [ -z ${ACTION} ] && abort if [ "${ARG2:0:1}" == "/" ] && [ -d ${ARG2} ]; then TCEDIR=${ARG2} [ -z ${TCEDIR} ] && TCEDIR=${DEFAULT_DIR} [ -d ${TCEDIR} ] || abort EXTNAME="" else TCEDIR=${TCEDIR%/*} [ -z ${TCEDIR##/*/} ] && TCEDIR=${DEFAULT_DIR} [ -d ${TCEDIR} ] || abort EXTNAME=${ARG2##/*/} [ ${EXTNAME%%.tcz} == ${EXTNAME} ] && EXTNAME=${EXTNAME}.tcz EXTNAME="${EXTNAME/-KERNEL/-${KERNELVER}}" fi updatedeps(){ echo -n "Updating .dep files from " echo "$TCEDIR" ls *.tcz | while read F do TARGET=${F##/*/}.dep TARGET="${TARGET/-KERNEL/-${KERNELVER}}" echo -n "." [ -f /tmp/"$TARGET" ] && rm -f /tmp/"$TARGET" wget -cq -P /tmp "$MIRROR"/"$TARGET" 2>/tmp/fetch_result if [ "$?" == 0 ]; then mv /tmp/"$TARGET" "$TCEDIR"/. else if grep -v 404 /tmp/fetch_result; then echo "$?" >> "$AUDIT_RESULTS" echo "Error on downloading of $F" >> "$AUDIT_RESULTS" echo "Could be a network issue or ..." >> "$AUDIT_RESULTS" echo "that this extension has a new name or is no longer supported!" >> "$AUDIT_RESULTS" fi fi done echo [ -s "$AUDIT_RESULTS" ] && echo "Errors occurred during audit. See /tmp/audit_results.txt" } builddb(){ > "$AUDIT_RESULTS" > "$TCE_DB" > "$TCE_LST" echo -n "Building Extension Database from " echo "$TCEDIR" ls *.tcz 2>/dev/null | sed 's/.*\///' | awk -v tce_lst="$TCE_LST" -v tce_db="$TCE_DB" ' function recursive_scan(name, optional, _, depfile, line, i, x) { gsub(/[\t ]+/, "", name) if (name) { sub(/\-KERNEL\.tcz/, "-"KERNELVER".tcz", name) if (name in MARK) { if (MARK[name] == 2) { RESULT[++IDX] = name for (x in MARK) { if (MARK[x] == 2) { LOOP[x] = name if (DEPTH[x] >= DEPTH[name]) LOOPITEM[name] = LOOPITEM[name]"\n"x } } } else { RESULT[++IDX] = "@#"name } } else { RESULT[++IDX] = name IRANGE[name"#1"] = IDX MARK[name] = 2 DEPTH[name] = ++DEPTHNUM if (system("test -f "optional"/"name) == 0) { depfile=optional"/"name".dep" while (getline line < depfile > 0) recursive_scan(line, optional) close(depfile) } MARK[name] = 1 DEPTHNUM -- IRANGE[name"#2"] = IDX } } } function output(idx1, idx2, _, name, i, refname) { for (i=idx1; i<=idx2; i++) { name=RESULT[i] if (! (name in PRINTED)) { PRINTED[name]=1 if (substr(name, 1, 2) == "@#") { refname = substr(name, 3) output(IRANGE[refname"#1"], IRANGE[refname"#2"]+0) } else { print name >> tce_db } } } } BEGIN {KERNELVER="'"$KERNELVER"'"; IDX=0; DEPTHNUM=0;} {recursive_scan($1, substr($2, 1, 1)=="/" ? $2 : ENVIRON["PWD"]); if (NR%5==0) printf ".";} END { for (name in MARK) system("test -f " name " && echo " name " >> " tce_lst) close(tce_lst) system("busybox sort -f "tce_lst" > /tmp/sort.$$ && mv /tmp/sort.$$ "tce_lst" 2>/dev/null") while (getline name < tce_lst > 0) { output(IRANGE[name"#1"], IRANGE[name"#2"]+0) delete PRINTED if (name in LOOP) print "Warning loop dependencies:"LOOPITEM[LOOP[name]] >> tce_db print "" >> tce_db } }' echo } dependson() { awk -v target="$1" -v results="$AUDIT_RESULTS" ' BEGIN { FS="\n" RS="" print "Has the following dependencies:" > results } { if ($1 == target) for (i=2; i <= NF; i=i+1 ) print $i >> results } ' < "$TCE_DB" } nodepends() { awk -v results="$AUDIT_RESULTS" ' BEGIN { FS="\n" RS="" print "The following extensions have no dependencies:" > results } { if (NF == 1) print $1 > results } ' < "$TCE_DB" } notrequired() { echo "The following are NOT required by any other extensions:" > "$AUDIT_WORK" while read F; do > "$AUDIT_RESULTS" requiredby "$F" [ -s "$AUDIT_RESULTS" ] || echo "$F" >> "$AUDIT_WORK" done < "$TCE_LST" mv "$AUDIT_WORK" "$AUDIT_RESULTS" } requiredby() { awk -v target="$1" -v results="$AUDIT_RESULTS" ' BEGIN { FS="\n" RS="" } { for (i=2; i <= NF; i=i+1 ) if ($i == target) print $1 > results } ' < "$TCE_DB" } auditall() { > "$AUDIT_RESULTS" while read F; do audit "$F" done < "$TCE_LST" } fetchmissing() { auditall for F in $(awk '{print $3}' $AUDIT_RESULTS | sort | uniq); do tce-load -wl "$F" 2>/dev/null done > "$AUDIT_RESULTS" } audit() { awk -v target="$1" -v list="$TCE_LST" -v results="$AUDIT_RESULTS" ' BEGIN { FS="\n" RS="" } { if ($1 == target) { for ( i = 2; i <= NF; i++ ) { result = system("grep -w ^"$i"$ "list" >/dev/null 2>&1") if (result == 1) print "For " target " " $i" is missing!" >> results } } } ' < "$TCE_DB" } #main cd "$TCEDIR" > "$AUDIT_RESULTS" case $1 in updatedeps) updatedeps builddb ;; builddb) builddb ;; dependson) dependson "$EXTNAME" ;; nodepends) nodepends ;; notrequired) notrequired ;; requiredby) requiredby "$EXTNAME" ;; auditall) auditall ;; fetchmissing) fetchmissing ;; audit) audit "$EXTNAME" "report" ;; delete) requiredby "$EXTNAME" if [ -s "$AUDIT_MARKED" ]; then for M in `cat "$AUDIT_MARKED"`; do sed -i '/'`basename "$M"`'/d' "$AUDIT_RESULTS" done fi if [ -s "$AUDIT_RESULTS" ]; then echo "$EXTNAME" "cannot be deleted." >> "$AUDIT_RESULTS" else awk 'BEGIN { FS="\n"; RS="" }/^'"$EXTNAME"'/' "$TCE_DB" > /tmp/audit_work.$$ if [ -s /tmp/audit_work.$$ ]; then cp /tmp/audit_work.$$ /tmp/audit_work2.$$ [ -s "$AUDIT_MARKED" ] && while read M; do echo ${M##*/} >> /tmp/audit_work2.$$; done < "$AUDIT_MARKED" for D in `cat /tmp/audit_work.$$`; do > "$AUDIT_RESULTS" requiredby "$D" RESULTS=` grep -vf /tmp/audit_work2.$$ "$AUDIT_RESULTS"` if [ "$RESULTS" = "" ]; then grep -q "$D" "$AUDIT_MARKED" 2>/dev/null || echo "$TCEDIR"/"$D" >> "$AUDIT_MARKED" grep -q "$D" /tmp/audit_results.$$ 2>/dev/null || echo "$TCEDIR"/"$D" >> /tmp/audit_results.$$ fi done rm /tmp/audit_work.$$ /tmp/audit_work2.$$ mv /tmp/audit_results.$$ "$AUDIT_RESULTS" fi fi ;; marked) if [ -s "$AUDIT_MARKED" ]; then sort "$AUDIT_MARKED" | uniq | tee /tmp/audit_results.$$ mv /tmp/audit_results.$$ "$AUDIT_MARKED" fi ;; clearlst) > "$AUDIT_MARKED" ;; remove) tce-remove exit 0 ;; *) abort ;; esac if [ -s "$AUDIT_RESULTS" ]; then cat "$AUDIT_RESULTS"; fi