<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<chapter id="chap-Defensive_Coding-Tasks-Temporary_Files">
  <title>Temporary files</title>
  <para>
    In this chapter, we describe how to create temporary files and
    directories, how to remove them, and how to work with programs
    which do not create files in ways that a safe with a shared
    directory for temporary files.  General file system manipulation
    is treated in a separate chapter, <xref
    linkend="chap-Defensive_Coding-Tasks-File_System"/>.
  </para>
  <para>
    Secure creation of temporary files has four different aspects.
  </para>
  <itemizedlist>
    <listitem>
      <para>
	The location of the directory for temporary files must be
	obtained in a secure manner (that is, untrusted environment
	variables must be ignored, see <xref
	linkend="sect-Defensive_Coding-Tasks-secure_getenv"/>).
      </para>
    </listitem>
    <listitem>
      <para>
	A new file must be created.  Reusing an existing file must be
	avoided (the <filename class="directory">/tmp</filename> race
	condition).  This is tricky because traditionally, system-wide
	temporary directories shared by all users are used.
      </para>
    </listitem>
    <listitem>
      <para>
	The file must be created in a way that makes it impossible for
	other users to open it.
      </para>
    </listitem>
    <listitem>
      <para>
	The descriptor for the temporary file should not leak to
	subprocesses.
      </para>
    </listitem>
  </itemizedlist>
  <para>
    All functions mentioned below will take care of these aspects.
  </para>
  <para>
    Traditionally, temporary files are often used to reduce memory
    usage of programs.  More and more systems use RAM-based file
    systems such as <literal>tmpfs</literal> for storing temporary
    files, to increase performance and decrease wear on Flash storage.
    As a result, spooling data to temporary files does not result in
    any memory savings, and the related complexity can be avoided if
    the data is kept in process memory.
  </para>

  <section id="chap-Defensive_Coding-Tasks-Temporary_Files-Location">
    <title>Obtaining the location of temporary directory</title>
    <para>
      Some functions below need the location of a directory which
      stores temporary files.  For C/C++ programs, use the following
      steps to obtain that directory:
    </para>
    <itemizedlist>
      <listitem>
	<para>
	  Use <function>secure_getenv</function> to obtain the value
	  of the <literal>TMPDIR</literal> environment variable.  If
	  it is set, convert the path to a fully-resolved absolute
	  path, using <literal>realpath(path, NULL)</literal>.  Check
	  if the new path refers to a directory and is writeable.  In
	  this case, use it as the temporary directory.
	</para>
      </listitem>
      <listitem>
	<para>
	  Fall back to <filename class="directory">/tmp</filename>.
	</para>
      </listitem>
    </itemizedlist>
    <para>
      In Python, you can use the <varname>tempfile.tempdir</varname>
      variable.
    </para>
    <para>
      Java does not support SUID/SGID programs, so you can use the
      <function>java.lang.System.getenv(String)</function> method to
      obtain the value of the <literal>TMPDIR</literal> environment
      variable, and follow the two steps described above.  (Java's
      default directory selection does not honor
      <literal>TMPDIR</literal>.)
    </para>
  </section>

  <section>
    <title>Named temporary files</title>
    <para>
      The <function>mkostemp</function> function creates a named
      temporary file.  You should specify the
      <literal>O_CLOEXEC</literal> flag to avoid file descriptor leaks
      to subprocesses. (Applications which do not use multiple threads
      can also use <function>mkstemp</function>, but libraries should
      use <function>mkostemp</function>.)  For determining the
      directory part of the file name pattern, see <xref
      linkend="chap-Defensive_Coding-Tasks-Temporary_Files-Location"/>.
    </para>
    <para>
      The file is not removed automatically.  It is not safe to rename
      or delete the file before processing, or transform the name in
      any way (for example, by adding a file extension).  If you need
      multiple temporary files, call <function>mkostemp</function>
      multiple times.  Do not create additional file names derived
      from the name provided by a previous
      <function>mkostemp</function> call.  However, it is safe to close
      the descriptor returned by <function>mkostemp</function> and
      reopen the file using the generated name.
    </para>
    <para>
      The Python class <literal>tempfile.NamedTemporaryFile</literal>
      provides similar functionality, except that the file is deleted
      automatically by default.  Note that you may have to use the
      <literal>file</literal> attribute to obtain the actual file
      object because some programming interfaces cannot deal with
      file-like objects. The C function <function>mkostemp</function>
      is also available as <function>tempfile.mkstemp</function>.
    </para>
    <para>
      In Java, you can use the
      <function>java.io.File.createTempFile(String, String,
      File)</function> function, using the temporary file location
      determined according to <xref
      linkend="chap-Defensive_Coding-Tasks-Temporary_Files-Location"/>.
      Do not use <function>java.io.File.deleteOnExit()</function> to
      delete temporary files, and do not register a shutdown hook for
      each temporary file you create.  In both cases, the deletion
      hint cannot be removed from the system if you delete the
      temporary file prior to termination of the VM, causing a memory
      leak.
    </para>
  </section>

  <section>
    <title>Temporary files without names</title>
    <para>
      The <function>tmpfile</function> function creates a temporary
      file and immediately deletes it, while keeping the file open.
      As a result, the file lacks a name and its space is deallocated
      as soon as the file descriptor is closed (including the implicit
      close when the process terminates).  This avoids cluttering the
      temporary directory with orphaned files.
    </para>
    <para>
      Alternatively, if the maximum size of the temporary file is
      known beforehand, the <function>fmemopen</function> function can
      be used to create a <literal>FILE *</literal> object which is
      backed by memory.
    </para>
    <para>
      In Python, unnamed temporary files are provided by the
      <literal>tempfile.TemporaryFile</literal> class, and the
      <literal>tempfile.SpooledTemporaryFile</literal> class provides
      a way to avoid creation of small temporary files.
    </para>
    <para>
      Java does not support unnamed temporary files.
    </para>
  </section>

  <section id="chap-Defensive_Coding-Tasks-Temporary_Directory">
    <title>Temporary directories</title>
    <para>
      The <function>mkdtemp</function> function can be used to create
      a temporary directory.  (For determining the directory part of
      the file name pattern, see <xref
      linkend="chap-Defensive_Coding-Tasks-Temporary_Files-Location"/>.)
      The directory is not automatically removed.  In Python, this
      function is available as <function>tempfile.mkdtemp</function>.
      In Java 7, temporary directories can be created using the
      <function>java.nio.file.Files.createTempDirectory(Path, String,
      FileAttribute...)</function> function.
    </para>
    <para>
      When creating files in the temporary directory, use
      automatically generated names, e.g., derived from a sequential
      counter.  Files with externally provided names could be picked
      up in unexpected contexts, and crafted names could actually
      point outside of the tempoary directory (due to
      <emphasis>directory traversal</emphasis>).
    </para>
    <para>
      Removing a directory tree in a completely safe manner is
      complicated.  Unless there are overriding performance concerns,
      the <application>rm</application> program should be used, with
      the <option>-rf</option> and <option>--</option> options.
    </para>
  </section>

  <section>
    <title>Compensating for unsafe file creation</title>
    <para>
      There are two ways to make a function or program which excepts a
      file name safe for use with temporary files. See
      <xref linkend="sect-Defensive_Coding-Tasks-Processes-Creation"/>,
      for details on subprocess creation.
    </para>
    <itemizedlist>
      <listitem>
	<para>
	  Create a temporary directory and place the file there.  If
	  possible, run the program in a subprocess which uses the
	  temporary directory as its current directory, with a
	  restricted environment.
	  Use generated names for all files in that temporary
	  directory.  (See <xref
	  linkend="chap-Defensive_Coding-Tasks-Temporary_Directory"/>.)
	</para>
      </listitem>
      <listitem>
	<para>
	  Create the temporary file and pass the generated file name
	  to the function or program.  This only works if the function
	  or program can cope with a zero-length existing file.  It is
	  safe only under additional assumptions:
	</para>
	<itemizedlist>
	  <listitem>
	    <para>
	      The function or program must not create additional files
	      whose name is derived from the specified file name or
	      are otherwise predictable.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
	      The function or program must not delete the file before
	      processing it.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
	      It must not access any existing files in the same
	      directory.
	    </para>
	  </listitem>
	</itemizedlist>
	<para>
	  It is often difficult to check whether these additional
	  assumptions are matched, therefore this approach is not
	  recommended.
	</para>
      </listitem>
    </itemizedlist>
  </section>
</chapter>
