AU: Update Downloader to support our image formats.

The downloader used to be dumb in the sense that it would pipe output
to either a DirectFileWriter or a DirectFileWriter via a
GzipDecompressingFileWriter, depending on if we were downloading an
update that was compressed or not. Sadly, things have gotten more
complex: we need to download to two partitions (kernel + rootfs), and
we may stream data via a DeltaPerformer (a type of FileWriter) to the
disk. Thus, the Downloader streams to either
1. gzip decompress->split_writer->direct to disk OR
2. delta performer

Other misc changes: Change FilesystemCopierAction to support
optionally copying the kernel partition rather than root partition.

InstallPlan struct: add an entry for destiation kernel partition.

Test Utils: a new ScopedTempFile class

Utils: support for getting the booted kernel partition device.

BUG=None
TEST=attached unittests

Review URL: http://codereview.chromium.org/1694025
diff --git a/utils.cc b/utils.cc
index 85d9e7d..83096d2 100644
--- a/utils.cc
+++ b/utils.cc
@@ -297,7 +297,7 @@
   return 0 == str.compare(0, prefix.size(), prefix);
 }
 
-const std::string BootDevice() {
+const string BootDevice() {
   string proc_cmdline;
   if (!ReadFileToString("/proc/cmdline", &proc_cmdline))
     return "";
@@ -324,6 +324,21 @@
   // TODO(adlr): use findfs to figure out UUID= or LABEL= filesystems
 }
 
+const string BootKernelDevice(const std::string& boot_device) {
+  // Currntly this assumes the last digit of the boot device is
+  // 3, 5, or 7, and changes it to 2, 4, or 6, respectively, to
+  // get the kernel device.
+  string ret = boot_device;
+  if (ret.empty())
+    return ret;
+  char last_char = ret[ret.size() - 1];
+  if (last_char == '3' || last_char == '5' || last_char == '7') {
+    ret[ret.size() - 1] = last_char - 1;
+    return ret;
+  }
+  return "";
+}
+
 bool MountFilesystem(const string& device,
                      const string& mountpoint,
                      unsigned long mountflags) {