Boost logo

Boost :

From: Alberto Barbati (abarbati_at_[hidden])
Date: 2003-01-01 13:08:30


Hi,

first of all, I want to thank Beman Dawes and all others that
contributed with the design and development of the Filesystem library.
It's a wonderful piece of work.

I just would like to propose a couple of additions that I believe are
very useful. Both features regard temporary files.

First proposal: I propose to add a function with a signature of this kind:

     path generate_path_for_temp_file();

the effect would be to generate a new (potentially unique) path suitable
to be used for a temporary files. A sample POSIX implementation could be
as simple as:

     #include <cstdio>
     path generate_path_for_temp_file()
     {
         char tmp_name[L_tmpnam];
         return path(tmpname(tmp_name), native);
     }

but there could also be platform-specific implementations. For example,
a Win32 sample implementation could use the GetTempPath/GetTempFileName
to create the path in the correct directory as in:

     #include <windows.h>
     path generate_path_for_temp_file()
     {
         char tmp_dir_path[MAX_PATH];
         char tmp_name[MAX_PATH];

         if(GetTempPathA(sizeof(tmp_dir_path), tmp_dir_path) == 0
             || GetTempFileNameA(tmp_dir_path, "$$$", 0, tmp_name) == 0)
         {
           boost::throw_exception(
               filesystem_error("unable to generate path for temporary
file", system_error));
         }

         return path(tmp_name, native);
     }

Open issues (to be discussed):

1) on Win32, GetTempFileName also create an empty file with the returned
name. Other platforms also have functions that atomically generates the
name *and* creates a file with such name. Should there be a
postcondition about the existence (or non-existence) of such a file?

2) Another useful signature could be:

     path generate_path_for_temp_file(const path& location_hint)

that would use the specified path as a hint (in an unspecified
platform-dependent way) to generate the path. For example, one may want
to generate a temporary file in a specified directory or physical drive,
overriding the system default, if any. On Win32 such a function could be
implemented as:

     #include <windows.h>
     path generate_path_for_temp_file(const path& hint)
     {
         char tmp_name[MAX_PATH];

         if(GetTempFileNameA(hint.native_directory_string().c_str(),
"$$$", 0, tmp_name) == 0)
         {
           boost::throw_exception(
               filesystem_error("unable to generate path for temporary
file", system_error));
         }

         return path(tmp_name, native);
     }

Second proposal: a stream class that encapsulates a temporary file, that
is a stream based on a file that is automatically deleted in the
stream's destructor. I am attaching a sample implementation. It's
implemented as a simple wrapper around fs::basic_fstream and
generate_path_for_temp() above.

Cheers,

Alberto


#ifndef BOOST_FILESYSTEM_TEMPSTREAM_HPP
#define BOOST_FILESYSTEM_TEMPSTREAM_HPP

#include <boost/filesystem/fstream.hpp>

namespace boost
{
  namespace filesystem
  {
    path generate_path_for_temp_file();
    path generate_path_for_temp_file(const path& hint);

    template < class charT, class traits = std::char_traits<charT> >
    class basic_tempstream : public basic_fstream<charT, traits>
    {
    public:
      // ctor always opens file
      explicit basic_tempstream(std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out)
        : m_path(generate_path_for_temp_file())
      {
        basic_fstream<charT, traits>::open(m_path, mode);
      }

      explicit basic_tempstream(const path& hint,
          std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out)
        : m_path(generate_path_for_temp_file(hint))
      {
        basic_fstream<charT, traits>::open(m_path, mode);
      }

      virtual ~basic_tempstream()
      {
        remove(m_path);
      }

      // intentionally hide inherited open()
      void open(std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out)
      {
        basic_fstream<charT, traits>::open(m_path, mode);
      }

      const path& path() const
      {
        return m_path;
      }

    private:
      filesystem::path m_path;
    };
 
    typedef basic_tempstream<char> tempstream;
# ifndef BOOST_NO_STD_WSTRING
    typedef basic_tempstream<wchar_t> wtempstream;
# endif

  } // namespace filesystem

} // namespace boost

#endif // BOOST_FILESYSTEM_TEMPSTREAM_HPP


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk