Sync with ToT

We've now put all the futility stuff into ToT, so we can stop work on this
branch. Make sure it matches m/master and just walk away...

BUG=none
BRANCH=none
TEST=none

Change-Id: Ic334c70ca43a9edc1ab391e09c10a92a20c6d0c7
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
diff --git a/Makefile b/Makefile
index 9ce42b6..cd39114 100644
--- a/Makefile
+++ b/Makefile
@@ -43,19 +43,23 @@
 # Stuff for 'make install'
 INSTALL = install
 DESTDIR = /usr/local/bin
-OLDDIR = /old_bins
+OLDDIR = old_bins
 
+# Where exactly do the pieces go?
+#  FT_DIR = futility target directory - where it will be on the target
+#  F_DIR  = futility install directory - where it gets put right now
+#  UB_DIR = userspace binary directory for futility's exec() targets
+#  VB_DIR = target vboot directory - for dev-mode-only helpers, keys, etc.
 ifeq (${MINIMAL},)
 # Host install just puts everything in one place
 FT_DIR=${DESTDIR}
 F_DIR=${DESTDIR}
-UB_DIR=${DESTDIR}${OLDDIR}
+UB_DIR=${DESTDIR}/${OLDDIR}
 else
 # Target install puts things into DESTDIR subdirectories
 FT_DIR=/usr/bin
 F_DIR=${DESTDIR}${FT_DIR}
-UB_DIR=${F_DIR}${OLDDIR}
-SB_DIR=${DESTDIR}/sbin
+UB_DIR=${F_DIR}/${OLDDIR}
 VB_DIR=${DESTDIR}/usr/share/vboot/bin
 endif
 
@@ -130,6 +134,10 @@
 CFLAGS += -DCHROMEOS_ENVIRONMENT -Wall -Werror # HEY: always want last two?
 endif
 
+ifneq (${OLDDIR},)
+CFLAGS += -DOLDDIR=${OLDDIR}
+endif
+
 ifneq (${DEBUG},)
 CFLAGS += -DVBOOT_DEBUG
 endif
diff --git a/futility/futility.c b/futility/futility.c
index 9029493..c30e3e8 100644
--- a/futility/futility.c
+++ b/futility/futility.c
@@ -18,7 +18,13 @@
 #include "futility.h"
 
 #define MYNAME "futility"
+#ifdef OLDDIR
+#define XSTR(A) STR(A)
+#define STR(A) #A
+#define SUBDIR XSTR(OLDDIR)
+#else
 #define SUBDIR "old_bins"
+#endif
 
 /* File to use for logging, if present */
 #define LOGFILE "/tmp/futility.log"
@@ -41,8 +47,8 @@
 behavior, or (until that functionality is complete) it will just exec\n\
 the original binary.\n\
 \n\
-In either case it may also record some usage information in /tmp to\n\
-help improve coverage and correctness.\n\
+In either case it can append some usage information to " LOGFILE "\n\
+to help improve coverage and correctness.\n\
 \n\
 If you invoke it directly instead of via a symlink, it requires one\n\
 argument, which is the name of the old binary to exec. That binary\n\
@@ -97,7 +103,7 @@
   }
 
   for (done = 0; done < len; done += n) {
-    n = write(log_fd, str+done, len-done);
+    n = write(log_fd, str + done, len - done);
     if (n < 0)
       return;
   }
@@ -156,13 +162,17 @@
     log_close();
 }
 
+#define CALLER_PREFIX "CALLER:"
 static void log_args(int argc, char *argv[])
 {
   int i;
   ssize_t r;
   pid_t parent;
   char buf[80];
-  char truename[PATH_MAX+10];
+  char str_caller[PATH_MAX + sizeof(CALLER_PREFIX)] = CALLER_PREFIX;
+  char *truename = str_caller + sizeof(CALLER_PREFIX) - 1;
+  /* Note: truename starts on the \0 from CALLER_PREFIX, so we can write
+   * PATH_MAX chars into truename and still append a \0 at the end. */
 
   log_open();
 
@@ -171,12 +181,11 @@
 
   /* Can we tell who called us? */
   parent = getppid();
-  snprintf(buf, 80, "/proc/%d/exe", parent);
-  strncat(truename, "CALLER:", 7);
-  r = readlink(buf, truename+7, PATH_MAX-1);
+  snprintf(buf, sizeof(buf), "/proc/%d/exe", parent);
+  r = readlink(buf, truename, PATH_MAX);
   if (r >= 0) {
-    truename[r+7] = '\0';
-    log_str(truename);
+    truename[r] = '\0';
+    log_str(str_caller);
   }
 
   /* Now log the stuff about ourselves */
@@ -238,13 +247,20 @@
 
   /* The old binaries live under the true executable. Find out where that is. */
   myproc = getpid();
-  snprintf(buf, 80, "/proc/%d/exe", myproc);
-  r = readlink(buf, truename, PATH_MAX-1);
+  snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc);
+  r = readlink(buf, truename, PATH_MAX - 1);
   if (r < 0) {
     fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0],
             buf, strerror(errno));
     exit(1);
+  } else if (r == PATH_MAX - 1) {
+    /* Yes, it might _just_ fit, but we'll count that as wrong anyway. We can't
+     * determine the right size using the example in the readlink manpage,
+     * because the /proc symlink returns an st_size of 0. */
+    fprintf(stderr, "%s is too long: %s => %s\n", MYNAME, argv[0], buf);
+    exit(1);
   }
+
   truename[r] = '\0';
   s = strrchr(truename, '/');           /* Find the true directory */
   if (s) {
@@ -253,9 +269,12 @@
     fprintf(stderr, "%s says %s doesn't make sense\n", MYNAME, truename);
     exit(1);
   }
-  /* We've allocated PATH_MAX. If the old binary path doesn't fit, it can't be
-   * in the filesystem. */
-  snprintf(oldname, PATH_MAX, "%s/%s/%s", truename, SUBDIR, progname);
+  /* If the old binary path doesn't fit, just give up. */
+  r = snprintf(oldname, PATH_MAX, "%s/%s/%s", truename, SUBDIR, progname);
+  if (r >= PATH_MAX) {
+    fprintf(stderr, "%s/%s/%s is too long\n", truename, SUBDIR, progname);
+    exit(1);
+  }
 
   fflush(0);
   execve(oldname, argv, envp);
diff --git a/futility/tests/common.sh b/futility/tests/common.sh
index 0105b0c..ed187d7 100755
--- a/futility/tests/common.sh
+++ b/futility/tests/common.sh
@@ -11,21 +11,22 @@
 COL_STOP='\E[0;m'
 
 # args: [message]
-function green {
+green() {
   echo -e "${COL_GREEN}$*${COL_STOP}"
 }
 
 # args: [message]
-function yellow {
+yellow() {
   echo -e "${COL_YELLOW}WARNING: $*${COL_STOP}"
 }
 
-function red {
+# args: [message]
+red() {
   echo -e "${COL_RED}$*${COL_STOP}"
 }
 
-# args: [nested level [message]]
-function error {
+# args: [nested level] [message]
+error() {
   local lev=${1:-}
   case "${1:-}" in
     [0-9]*)
@@ -36,11 +37,11 @@
       ;;
   esac
   local x=$(caller $lev)
-  local cline=${x%% *}
-  local cfunc=${x#* }
-  cfunc=${cfunc##*/}
+  local cline="${x%% *}"
+  local cfile="${x#* }"
+  cfile="${cfile##*/}"
   local args="$*"
-  local spacer=${args:+: }
-  red "at ${cfunc}, line ${cline}${spacer}${args}" 1>&2
+  local spacer="${args:+: }"
+  red "at ${cfile}, line ${cline}${spacer}${args}" 1>&2
   exit 1
 }