/ src / common / linux / scoped_tmpfile.cc
scoped_tmpfile.cc
  1  // Copyright 2022 Google LLC
  2  //
  3  // Redistribution and use in source and binary forms, with or without
  4  // modification, are permitted provided that the following conditions are
  5  // met:
  6  //
  7  //     * Redistributions of source code must retain the above copyright
  8  // notice, this list of conditions and the following disclaimer.
  9  //     * Redistributions in binary form must reproduce the above
 10  // copyright notice, this list of conditions and the following disclaimer
 11  // in the documentation and/or other materials provided with the
 12  // distribution.
 13  //     * Neither the name of Google LLC nor the names of its
 14  // contributors may be used to endorse or promote products derived from
 15  // this software without specific prior written permission.
 16  //
 17  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 19  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 20  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 21  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 22  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 23  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 24  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 25  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 26  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 27  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 28  
 29  // Utility class for creating a temporary file that is deleted in the
 30  // destructor.
 31  
 32  #ifdef HAVE_CONFIG_H
 33  #include <config.h>  // Must come first
 34  #endif
 35  
 36  #include "common/linux/scoped_tmpfile.h"
 37  
 38  #include <fcntl.h>
 39  #include <stdlib.h>
 40  #include <string.h>
 41  #include <sys/types.h>
 42  #include <unistd.h>
 43  
 44  #include "common/linux/eintr_wrapper.h"
 45  
 46  #if !defined(__ANDROID__)
 47  #define TEMPDIR "/tmp"
 48  #else
 49  #define TEMPDIR "/data/local/tmp"
 50  #endif
 51  
 52  namespace google_breakpad {
 53  
 54  ScopedTmpFile::ScopedTmpFile() = default;
 55  
 56  ScopedTmpFile::~ScopedTmpFile() {
 57    if (fd_ >= 0) {
 58      close(fd_);
 59      fd_ = -1;
 60    }
 61  }
 62  
 63  bool ScopedTmpFile::InitEmpty() {
 64    // Prevent calling Init when fd_ is already valid, leaking the file.
 65    if (fd_ != -1) {
 66      return false;
 67    }
 68  
 69    // Respect the TMPDIR environment variable.
 70    const char* tempdir = getenv("TMPDIR");
 71    if (!tempdir) {
 72      tempdir = TEMPDIR;
 73    }
 74  
 75    // Create a temporary file that is not linked in to the filesystem, and that
 76    // is only accessible by the current user.
 77    fd_ = open(tempdir, O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
 78  
 79    return fd_ >= 0;
 80  }
 81  
 82  bool ScopedTmpFile::InitString(const char* text) {
 83    return InitData(text, strlen(text));
 84  }
 85  
 86  bool ScopedTmpFile::InitData(const void* data, size_t data_len) {
 87    if (!InitEmpty()) {
 88      return false;
 89    }
 90  
 91    return SetContents(data, data_len);
 92  }
 93  
 94  bool ScopedTmpFile::SetContents(const void* data, size_t data_len) {
 95    ssize_t r = HANDLE_EINTR(write(fd_, data, data_len));
 96    if (r != static_cast<ssize_t>(data_len)) {
 97      return false;
 98    }
 99  
100    return 0 == lseek(fd_, 0, SEEK_SET);
101  }
102  
103  }  // namespace google_breakpad