Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

vul_temp_filename.cxx

Go to the documentation of this file.
00001 // This is core/vul/vul_temp_filename.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vul_temp_filename.h"
00007 #include <vcl_string.h>
00008 #include <vcl_ctime.h>
00009 #include <vcl_cstdlib.h> // for rand/srand
00010 
00011 #if defined(VCL_BORLAND) || defined (VCL_VC)
00012 # include <vcl_cstdio.h> // for _tempnam on borland (and stlport5 with VC8)
00013 #endif
00014 
00015 #if defined(VCL_VC) || defined(VCL_BORLAND) || defined(__MINGW32__)
00016   #include <Windows.h>
00017 #else
00018 #if defined(unix) || defined(__unix)
00019   // Helper functions for Unix
00020 
00021   #include <stdio.h>  // for P_tmpdir
00022   #include <unistd.h> // for unlink
00023   #include <fcntl.h>  // for O_CREATE,...
00024 
00025   namespace {
00026     // The filename is okay if it doesn't exist and can be opened for
00027     // writing.
00028     bool is_okay( const vcl_string& name )
00029     {
00030       bool okay = true;
00031       int fd = open( name.c_str(), O_CREAT|O_EXCL );
00032       if ( fd == -1 ) {
00033         okay = false;
00034       } else {
00035         unlink( name.c_str() );
00036         close( fd );
00037       }
00038       return okay;
00039     }
00040 
00041 
00042     // Initialise the random number seed with the time.  Maybe need to
00043     // include things like (Unix) process id, but I don't think the
00044     // randomness is that crucial.
00045     int init_randomizer()
00046     {
00047       vcl_srand( vcl_time( 0 ) );
00048       return 0;
00049     }
00050     static int random_seed_trigger = init_randomizer();
00051 
00052     char random_letter()
00053     {
00054       // Make sure the random character is a letter.
00055       int r = vcl_rand() % (26+26); // 26 uppercase and 26 lowercase letters
00056       return (r<26) ? char('A'+r) : char('a'+r-26);
00057     }
00058 
00059     char random_char()
00060     {
00061       // Make sure the random character is a letter or number.
00062       int r = vcl_rand() % (26+26+10); // 2x26 letters, 10 digits
00063       return (r<26) ? char('A'+r) : (r<52) ? char('a'+r-26) : char('0'+r-52);
00064     }
00065   }
00066 #else
00067 # warning "This is neither unix nor MS-windows - please add specifics to " __FILE__
00068 #endif
00069 #endif
00070 
00071 vcl_string
00072 vul_temp_filename( )
00073 {
00074 #if defined(VCL_VC) || defined(VCL_BORLAND) || defined(__MINGW32__)
00075   char path[ _MAX_PATH ];
00076   char* file;
00077   if ( GetTempPath( _MAX_PATH, path ) == 0 )
00078     return "";
00079   // Can't use GetTempFileName, because the function actually creates the
00080   // temporary file! This would mean that every call to this function creates
00081   // yet another file that will lie around if the caller doesn't use the generated
00082   // filename. And I don't trust the implementation enough to just unlink the file
00083   // before returning.
00084 # if defined(VCL_BORLAND_56)
00085   file = std::_tempnam( path, "" );
00086 # else
00087   file = _tempnam( path, "" );
00088 # endif
00089   if ( file == 0 )
00090     return "";
00091   return file;
00092 #else
00093 #if defined(unix) || defined(__unix)
00094   // Don't use tmpnam, since it causes linker warnings (and sometimes
00095   // linker errors). Instead reimplement. Sigh.
00096   const unsigned int num_char_in_filename = 7+1; // should always be at least 1
00097   vcl_string filename;
00098   vcl_string tempdir;
00099   unsigned int count = 0;
00100   bool okay = false;
00101 
00102   if ( vcl_getenv( "TMP" ) ) {
00103     tempdir = vcl_getenv( "TMP" );
00104   } else {
00105     tempdir = P_tmpdir; // defined in stdio.h
00106   }
00107   char lastchar = ( tempdir.size() > 0 ) ? tempdir[tempdir.size()-1] : ' ';
00108   if (lastchar != '/' && lastchar != '\\')
00109     tempdir += "/";
00110 
00111   while ( !okay && count < 10 ) {
00112     char buf[ num_char_in_filename+1 ];
00113     buf[0] = random_letter(); // make sure first char is a letter
00114     for ( unsigned int i=1; i < num_char_in_filename; ++i )
00115       buf[i] = random_char();
00116     buf[num_char_in_filename] = '\0';
00117     filename = tempdir + buf;
00118     ++count;
00119     okay = is_okay( filename );
00120   };
00121 
00122   if ( okay )
00123     return filename;
00124   else
00125     return "";
00126 #else
00127 # warning "This is neither unix nor MS-windows - please add specifics to " __FILE__
00128 #endif
00129 #endif
00130 }

Generated on Thu Jan 10 14:41:00 2008 for core/vul by  doxygen 1.4.4