AU: Handle firmware update failure when booted from FW slot B.

The firmware updater will fail if we are booted into FW slot B and we
try to update firmware. We shouldn't treat this like a usual update
failure because trying again won't help until we reboot. Thus, with
this CL, we detect this case and request a reboot from the
user. Technically this request is a lie, b/c we are reusing the reboot
request mechanism which tells the user an update has been applied and
thus must be rebooted. We accept this fib since this situation is very
rare: use would have to have 2 FW update updates in a row w/o any
extra boots between.

Also, fix error code in subprocess.

Also, remove execute permissions on a bunch of source files.

BUG=chromium-os:14343
TEST=unittests, tested updates on machine that success, fail, have FW B failure

Review URL: http://codereview.chromium.org/6880077

Change-Id: I2509c6e1c9c9da3ff1ea27da4861c4850bd4d000
diff --git a/postinstall_runner_action_unittest.cc b/postinstall_runner_action_unittest.cc
index 05acb4c..2db4edc 100644
--- a/postinstall_runner_action_unittest.cc
+++ b/postinstall_runner_action_unittest.cc
@@ -31,7 +31,7 @@
 
 class PostinstallRunnerActionTest : public ::testing::Test {
  public:
-  void DoTest(bool do_losetup, bool do_err_script);
+  void DoTest(bool do_losetup, int err_code);
 };
 
 class PostinstActionProcessorDelegate : public ActionProcessorDelegate {
@@ -60,20 +60,25 @@
 
 TEST_F(PostinstallRunnerActionTest, RunAsRootSimpleTest) {
   ASSERT_EQ(0, getuid());
-  DoTest(true, false);
+  DoTest(true, 0);
 }
 
 TEST_F(PostinstallRunnerActionTest, RunAsRootCantMountTest) {
   ASSERT_EQ(0, getuid());
-  DoTest(false, false);
+  DoTest(false, 0);
 }
 
 TEST_F(PostinstallRunnerActionTest, RunAsRootErrScriptTest) {
   ASSERT_EQ(0, getuid());
-  DoTest(true, true);
+  DoTest(true, 1);
 }
 
-void PostinstallRunnerActionTest::DoTest(bool do_losetup, bool do_err_script) {
+TEST_F(PostinstallRunnerActionTest, RunAsRootFirmwareBErrScriptTest) {
+  ASSERT_EQ(0, getuid());
+  DoTest(true, 2);
+}
+
+void PostinstallRunnerActionTest::DoTest(bool do_losetup, int err_code) {
   ASSERT_EQ(0, getuid()) << "Run me as root. Ideally don't run other tests "
                          << "as root, tho.";
 
@@ -107,8 +112,8 @@
                                "  touch %s/postinst_called\n"
                                "fi\n",
                                cwd.c_str());
-  if (do_err_script) {
-    script = "#!/bin/bash\nexit 1";
+  if (err_code) {
+    script = StringPrintf("#!/bin/bash\nexit %d", err_code);
   }
   ASSERT_TRUE(WriteFileString(mountpoint + "/postinst", script));
   ASSERT_EQ(0, System(string("chmod a+x ") + mountpoint + "/postinst"));
@@ -161,16 +166,18 @@
   ASSERT_FALSE(processor.IsRunning());
 
   EXPECT_TRUE(delegate.code_set_);
-  EXPECT_EQ(do_losetup && !do_err_script, delegate.code_ == kActionCodeSuccess);
-  EXPECT_EQ(do_losetup && !do_err_script,
+  EXPECT_EQ(do_losetup && !err_code, delegate.code_ == kActionCodeSuccess);
+  EXPECT_EQ(do_losetup && !err_code,
             !collector_action.object().install_path.empty());
-  if (do_losetup && !do_err_script) {
+  if (do_losetup && !err_code) {
     EXPECT_TRUE(install_plan == collector_action.object());
   }
+  if (err_code == 2)
+    EXPECT_EQ(kActionCodePostinstallBootedFromFirmwareB, delegate.code_);
 
   struct stat stbuf;
   int rc = lstat((string(cwd) + "/postinst_called").c_str(), &stbuf);
-  if (do_losetup && !do_err_script)
+  if (do_losetup && !err_code)
     ASSERT_EQ(0, rc);
   else
     ASSERT_LT(rc, 0);