AU: prepend TMPDIR when creating a temp file/directory

This changes the behavior of utils::MakeTemp{File,Directory} to prepend
TMPDIR (or /tmp, if not defined) to the given path template. That is,
unless the user provided an absolute path, or a path that is explicitly
relative to the current directory (starts with ./ or ../).

BUG=chromium:253622
TEST=None

Change-Id: Ibe11b279f8f4e9ba97bb2d44867595f76bbf632a
Reviewed-on: https://chromium-review.googlesource.com/182098
Tested-by: Gilad Arnold <garnold@chromium.org>
Reviewed-by: Don Garrett <dgarrett@chromium.org>
Commit-Queue: Gilad Arnold <garnold@chromium.org>
diff --git a/omaha_request_action_unittest.cc b/omaha_request_action_unittest.cc
index 428a286..015f396 100644
--- a/omaha_request_action_unittest.cc
+++ b/omaha_request_action_unittest.cc
@@ -1731,7 +1731,7 @@
       "CHROMEOS_IS_POWERWASH_ALLOWED=true\n"
       "CHROMEOS_RELEASE_TRACK=stable-channel\n"));
   OmahaRequestParams params = kDefaultTestParams;
-  params.set_root(string("./") + test_dir);
+  params.set_root(test_dir);
   params.SetLockDown(false);
   params.Init("1.2.3.4", "", 0);
   EXPECT_EQ("canary-channel", params.current_channel());
@@ -1778,7 +1778,7 @@
       test_dir + kStatefulPartition + "/etc/lsb-release",
       "CHROMEOS_RELEASE_TRACK=canary-channel\n"));
   OmahaRequestParams params = kDefaultTestParams;
-  params.set_root(string("./") + test_dir);
+  params.set_root(test_dir);
   params.SetLockDown(false);
   params.Init("5.6.7.8", "", 0);
   EXPECT_EQ("stable-channel", params.current_channel());
diff --git a/omaha_request_params_unittest.cc b/omaha_request_params_unittest.cc
index a4dfdc9..5b615b8 100644
--- a/omaha_request_params_unittest.cc
+++ b/omaha_request_params_unittest.cc
@@ -41,7 +41,7 @@
     // unintended reuse of state across tests.
     OmahaRequestParams new_params(&mock_system_state_);
     params_ = new_params;
-    params_.set_root(string("./") + test_dir_);
+    params_.set_root(test_dir_);
     params_.SetLockDown(false);
   }
 
@@ -331,7 +331,7 @@
       "CHROMEOS_AUSERVER=http://www.google.com"));
   {
     OmahaRequestParams params(&mock_system_state_);
-    params.set_root(string("./") + test_dir_);
+    params.set_root(test_dir_);
     params.SetLockDown(false);
     EXPECT_TRUE(params.Init("", "", false));
     params.SetTargetChannel("canary-channel", false);
@@ -353,7 +353,7 @@
       "CHROMEOS_AUSERVER=http://www.google.com"));
   {
     OmahaRequestParams params(&mock_system_state_);
-    params.set_root(string("./") + test_dir_);
+    params.set_root(test_dir_);
     params.SetLockDown(false);
     EXPECT_TRUE(params.Init("", "", false));
     params.SetTargetChannel("canary-channel", true);
diff --git a/omaha_response_handler_action_unittest.cc b/omaha_response_handler_action_unittest.cc
index 6fe48da..41e8c67 100644
--- a/omaha_response_handler_action_unittest.cc
+++ b/omaha_response_handler_action_unittest.cc
@@ -301,7 +301,7 @@
 
   MockSystemState mock_system_state;
   OmahaRequestParams params(&mock_system_state);
-  params.set_root(string("./") + test_dir);
+  params.set_root(test_dir);
   params.SetLockDown(false);
   params.Init("1.2.3.4", "", 0);
   EXPECT_EQ("canary-channel", params.current_channel());
@@ -344,7 +344,7 @@
 
   MockSystemState mock_system_state;
   OmahaRequestParams params(&mock_system_state);
-  params.set_root(string("./") + test_dir);
+  params.set_root(test_dir);
   params.SetLockDown(false);
   params.Init("5.6.7.8", "", 0);
   EXPECT_EQ("stable-channel", params.current_channel());
diff --git a/utils.cc b/utils.cc
index 7e5cf75..f2b7450 100644
--- a/utils.cc
+++ b/utils.cc
@@ -476,9 +476,24 @@
   return path;
 }
 
-bool MakeTempFile(const std::string& filename_template,
+// If |path| is absolute, or explicit relative to the current working directory,
+// leaves it as is. Otherwise, if TMPDIR is defined in the environment and is
+// non-empty, prepends it to |path|. Otherwise, prepends /tmp.  Returns the
+// resulting path.
+static const string PrependTmpdir(const string& path) {
+  if (path[0] == '/' || StartsWithASCII(path, "./", true) ||
+      StartsWithASCII(path, "../", true))
+    return path;
+
+  const char *tmpdir = getenv("TMPDIR");
+  const string prefix = (tmpdir && *tmpdir ? tmpdir : "/tmp");
+  return prefix + "/" + path;
+}
+
+bool MakeTempFile(const std::string& base_filename_template,
                   std::string* filename,
                   int* fd) {
+  const string filename_template = PrependTmpdir(base_filename_template);
   DCHECK(filename || fd);
   vector<char> buf(filename_template.size() + 1);
   memcpy(&buf[0], filename_template.data(), filename_template.size());
@@ -497,8 +512,9 @@
   return true;
 }
 
-bool MakeTempDirectory(const std::string& dirname_template,
+bool MakeTempDirectory(const std::string& base_dirname_template,
                        std::string* dirname) {
+  const string dirname_template = PrependTmpdir(base_dirname_template);
   DCHECK(dirname);
   vector<char> buf(dirname_template.size() + 1);
   memcpy(&buf[0], dirname_template.data(), dirname_template.size());
diff --git a/utils.h b/utils.h
index 710c5db..f48a6ce 100644
--- a/utils.h
+++ b/utils.h
@@ -110,19 +110,25 @@
 // THAT YOUR PROCESS WILL BE THE ONLY THING WRITING FILES IN THIS DIRECTORY.
 std::string TempFilename(std::string path);
 
-// Calls mkstemp() with the template passed. Returns the filename in the
-// out param filename. If fd is non-NULL, the file fd returned by mkstemp
-// is not close()d and is returned in the out param 'fd'. However, if
-// fd is NULL, the fd from mkstemp() will be closed.
-// The last six chars of the template must be XXXXXX.
-// Returns true on success.
-bool MakeTempFile(const std::string& filename_template,
+// If |base_filename_template| is neither absolute (starts with "/") nor
+// explicitly relative to the current working directory (starts with "./" or
+// "../"), then it is prepended the value of TMPDIR, which defaults to /tmp if
+// it isn't set or is empty.  It then calls mkstemp(3) with the resulting
+// template.  Writes the name of a new temporary file to |filename|. If |fd| is
+// non-NULL, the file descriptor returned by mkstemp is written to it and kept
+// open; otherwise, it is closed. The template must end with "XXXXXX". Returns
+// true on success.
+bool MakeTempFile(const std::string& base_filename_template,
                   std::string* filename,
                   int* fd);
 
-// Calls mkdtemp() with the template passed. Returns the generated dirname
-// in the dirname param. Returns TRUE on success. dirname must not be NULL.
-bool MakeTempDirectory(const std::string& dirname_template,
+// If |base_filename_template| is neither absolute (starts with "/") nor
+// explicitly relative to the current working directory (starts with "./" or
+// "../"), then it is prepended the value of TMPDIR, which defaults to /tmp if
+// it isn't set or is empty.  It then calls mkdtemp() with the resulting
+// template. Writes the name of the new temporary directory to |dirname|.
+// The template must end with "XXXXXX". Returns true on success.
+bool MakeTempDirectory(const std::string& base_dirname_template,
                        std::string* dirname);
 
 // Deletes a directory and all its contents synchronously. Returns true