From 94dd35b3f635ef665426c4b339fe69982a8fb392 Mon Sep 17 00:00:00 2001 From: Eygene Ryabinkin Date: Fri, 27 Nov 2009 15:06:09 +0300 Subject: [PATCH 4/4] security/vuxml: teach newentry.sh to accept existing entries Now newentry.sh can add not only generic template for the new entry, but existing entries as well. Both plain entries and patches are accepted. This mode was created mainly due to the fact that vuln.xml changes frequently and if one sends patch for the obsolete version of vuln.xml, the patch won't be applied cleanly and manual work is needed. Script automates such insertions. Moreover, plain VuXML entries that are not patches, but are just pieces of vuln.xml can be sent via PRs -- they are inserted automatically too. 'make addentry E=/path/to/entry/file' will do the work -- Makefile was extended to handle the new target. Signed-off-by: Eygene Ryabinkin --- security/vuxml/Makefile | 6 ++ security/vuxml/files/newentry.sh | 115 +++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/security/vuxml/Makefile b/security/vuxml/Makefile index d347c39..8aa177e 100644 --- a/security/vuxml/Makefile +++ b/security/vuxml/Makefile @@ -83,4 +83,10 @@ tidy: newentry: @${SH} ${FILESDIR}/newentry.sh "${VUXML_FILE}" +addentry: +.if empty(E) +.error "Set make variable E to the location of the VuXML entry to be added." +.endif + @${SH} ${FILESDIR}/newentry.sh -i "${E}" "${VUXML_FILE}" + .include diff --git a/security/vuxml/files/newentry.sh b/security/vuxml/files/newentry.sh index f2b9e61..d546a79 100644 --- a/security/vuxml/files/newentry.sh +++ b/security/vuxml/files/newentry.sh @@ -1,5 +1,87 @@ #! /bin/sh +# Patch detection strategy: we are looking for the three successive +# lines starting with "--- ", "+++ " and "@@ [+-]". The next line +# should start with space. This catches unified diffs. +# +# The number of the line where the patch contents start (the line with +# first '@@ [+-]') is printed to the standard output if the patch was +# really found. +is_patch () { + awk ' +BEGIN { seen_minus = 0; seen_plus = 0; seen_at = 0; diff = 0 } +/^--- / { seen_minus = 1; seen_plus = 0; seen_at = 0; diff = 0; next; } +seen_minus == 1 && /^\+\+\+ / { seen_plus = 1; next; } +seen_plus == 1 && /^@@ [+-]/ { seen_at = 1; next; } +seen_at == 1 && /^ / { print FNR; diff = 1; exit(0); } +{ seen_minus = 0; seen_plus = 0; seen_at = 0; } +END { exit (diff != 1); } +' "$1" +} + +# Checks if the patch contains one continuous hunk that contains +# only additions. +# Arguments: +# $1 -- patch filename; +# $2 -- line where patch contents start. +is_continuous_patch () { + + if [ -z "$1" -o -z "$2" ]; then + false + return + fi + awk -v start="$2" ' +BEGIN { blks = 0; in_blk = 0; } +FNR < start { next; } +/^-/ { exit(1); } +in_blk == 0 && /^+/ { in_blk = 1; blks++; if (blks > 1) { exit(1); } next; } +in_blk == 1 && !/^+/ { in_blk = 0; next; } +END { exit(blks != 1); }; +' "$1" +} + +# $1 is the file with the existing VuXML entry; it is guaranteed +# to be a real file. +# +# We should check if the supplied file contains a patch that has +# one continuous entry that is meant to be added -- only such files +# are treated as patches that add VuXML entries. If patch has more +# than one chunk or it deletes anything, we won't accept it. +# +# For the non-patch files, we will add them "as is". + +existing_entry () { + local patch_start + + if [ -z "$1" ]; then + false + return + fi + + # Plain file? Just cat it! + patch_start=`is_patch "$1"` + if [ "$?" != 0 ]; then + cat "$1" + echo + return + fi + + if is_continuous_patch "$1" "$patch_start"; then + awk -v start="$patch_start" ' +FNR < start { next; } +{ print; } +' "$1" | grep '^\+' | sed -e's/^\+//' + else + cat >&2 << EOF +Input VuXML entry looks like a patch, but it doesn't contain a single +hunk that I can use as the entry body. Human insight is needed, may +be it is better to merge the entry by hand. +EOF + false + return + fi +} + new_entry () { local vid discovery entry @@ -40,7 +122,7 @@ EOF } usage () { - echo "Usage: newentry.sh /path/to/vuxml/document" >&2 + echo "Usage: newentry.sh [-i /existing/entry] /path/to/vuxml/document" >&2 } cleanup() { @@ -49,6 +131,31 @@ cleanup() { fi } +while getopts "i:h" opt; do + case "$opt" in + h) + usage + exit 0 + ;; + i) + if [ ! -e "$OPTARG" ]; then + echo "File '$OPTARG' does not exist." >&2 + exit 1 + fi + entry="$OPTARG" + ;; + ?) + usage + exit 1 + ;; + -) + break + ;; + esac +done + +shift $(($OPTIND - 1)) + vuxml_file="$1" if [ -z "${vuxml_file}" ]; then usage @@ -60,7 +167,11 @@ trap cleanup EXIT 1 2 13 15 tmp="`mktemp ${TMPDIR:-/tmp}/vuxml.XXXXXXXXXX`" || exit 1 awk '/^<\?/,/^> "${tmp}" || exit 1 -new_entry >> "${tmp}" || exit 1 +if [ -n "$entry" ]; then + existing_entry "$entry" >> "${tmp}" || exit 1 +else + new_entry >> "${tmp}" || exit 1 +fi awk '/^[[:space:]]+> "${tmp}" || exit 1 -- 1.6.5.3