PLplot 5.9.6
plstdio.c
00001 /* $Id$
00002  *
00003  * Standardized I/O handler for PLplot.
00004  *
00005  * Copyright (C) 2006  Jim Dishaw
00006  * Copyright (C) 2006  Hazen Babcock
00007  *
00008  * This file is part of PLplot.
00009  *
00010  * PLplot is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU Library General Public License as published
00012  * by the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * PLplot is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public License
00021  * along with PLplot; if not, write to the Free Software
00022  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00023  *
00024  */
00025 
00026 #define NEED_PLDEBUG
00027 #include "plplotP.h"
00028 
00029 #if defined ( MSDOS ) || defined ( WIN32 )
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <fcntl.h>
00033 #endif
00034 
00035 /* For Visual C++ 2005 and later mktemp() and open() are deprecated (see
00036  * http://msdn.microsoft.com/en-us/library/ms235413.aspx and
00037  * http://msdn.microsoft.com/en-us/library/ms235491.aspx). mktemp()
00038  * is redefined to _mktemp() as well as open() to _open(). In addition
00039  * we need to include io.h.
00040  */
00041 #if defined ( _MSC_VER ) && _MSC_VER >= 1400
00042 #include <io.h>
00043 #define mktemp    _mktemp
00044 #define open      _open
00045 #define fdopen    _fdopen
00046 #endif
00047 /*
00048  * plio_write()
00049  *
00050  * Writes the contents of buf to stream.  Handles any I/O error conditions
00051  * so that the caller can "fire and forget."
00052  */
00053 
00054 void
00055 plio_fwrite( void *buf, size_t size, size_t nmemb, FILE *stream )
00056 {
00057     size_t bytes;
00058 
00059     dbug_enter( "plio_fwrite" );
00060 
00061     /* Exit if there is nothing to write */
00062     if ( size == 0 || nmemb == 0 )
00063         return;
00064 
00065     /* Clear the error flag for this steam */
00066     clearerr( stream );
00067 
00068     bytes = fwrite( buf, size, nmemb, stream );
00069 
00070     if ( ferror( stream ) )
00071     {
00072         /* Perhaps we can add a flag (global or per output stream)
00073          * in order to decide if we should abort or warn.  I think
00074          * I/O errors should generate an abort  */
00075         plabort( "Error writing to file" );
00076     }
00077 }
00078 
00079 /*
00080  * plio_read()
00081  *
00082  * Read from stream into buf.  Like plio_write(), this function will
00083  * handle any I/O error conditions.
00084  */
00085 
00086 void
00087 plio_fread( void *buf, size_t size, size_t nmemb, FILE *stream )
00088 {
00089     size_t bytes;
00090 
00091     dbug_enter( "plio_fread" );
00092 
00093     /* If the buffer has a size of zero, we should complain */
00094     if ( size == 0 || nmemb == 0 )
00095     {
00096         plwarn( "Zero length buffer size in plio_read, returning" );
00097         return;
00098     }
00099 
00100     /* Clear the error flag for this steam */
00101     clearerr( stream );
00102 
00103     bytes = fread( buf, size, nmemb, stream );
00104 
00105     if ( ferror( stream ) )
00106     {
00107         /* The read resulted in an error */
00108         plabort( "Error reading from file" );
00109     }
00110 }
00111 
00112 /*
00113  * plio_fgets()
00114  *
00115  * Read from stream into buf.  This version of fgets is designed for the occasions
00116  * where the caller wants to ignore the return value.
00117  *
00118  * NOTE: If one is reading from a file until an EOF condition, fgets() is better suited
00119  * than this function, i.e.
00120  *
00121  *     while(fgets(buf, size, fp) != NULL) { ... do some stuff ... }
00122  *
00123  * rather than
00124  *
00125  *     while(!feof(fp)) { plio_fgets(buf, size, fp);  ... do some stuff ... }
00126  *
00127  * which would require checking for an empty buffer.
00128  */
00129 
00130 void
00131 plio_fgets( char *buf, int size, FILE *stream )
00132 {
00133     char *s;
00134 
00135     dbug_enter( "plio_fgets" );
00136 
00137     /* If the buffer has a size of zero, we should complain */
00138     if ( size == 0 )
00139     {
00140         plwarn( "Zero length buffer size in plio_fgets, returning" );
00141         return;
00142     }
00143 
00144     /* Clear the error flag for this steam */
00145     clearerr( stream );
00146 
00147     s = fgets( buf, size, stream );
00148 
00149     if ( s == NULL && ferror( stream ) )
00150     {
00151         /* The read resulted in an error */
00152         plabort( "Error reading from file" );
00153     }
00154 }
00155 
00156 /*
00157  * pl_create_tempfile()
00158  *
00159  * Securely create a temporary file and return a file handle to it.
00160  * This provides cross-platform compatibility and also adds some
00161  * additional functionality over mkstemp in that it honours the TMP /
00162  * TMPDIR / TEMP environment variables.
00163  *
00164  * The function returns the file handle.
00165  *
00166  * If the fname variable is not NULL, then on return it will contain
00167  * a pointer to the full temporary file name. This will be allocated
00168  * with malloc. It is the caller's responsibility to ensure this
00169  * memory is free'd and to ensure the file is deleted after use.
00170  * If fname is NULL then the file will be automatically deleted
00171  * when it is closed.
00172  */
00173 FILE *
00174 pl_create_tempfile( char **fname )
00175 {
00176     int        flags;
00177     FILE       *fd;
00178     char       *tmpdir;
00179     char       *template;
00180     const char *tmpname = "plplot_XXXXXX";
00181 
00182 #if defined ( MSDOS ) || defined ( WIN32 )
00183     tmpdir = getenv( "TEMP" );
00184 #else
00185     tmpdir = getenv( "TMPDIR" );
00186 #endif
00187 
00188 /* The P_TMPDIR macro is defined in stdio.h on many UNIX systems - try that */
00189 #ifdef P_TMPDIR
00190     if ( tmpdir == NULL )
00191         tmpdir = P_TMPDIR;
00192 #endif
00193 
00194     if ( tmpdir == NULL )
00195     {
00196 #if defined ( MSDOS ) || defined ( WIN32 )
00197         tmpdir = "c:\\windows\\Temp";
00198 #else
00199         tmpdir = "/tmp";
00200 #endif
00201     }
00202 
00203     /* N.B. Malloc ensures template is long enough so strcpy and strcat are safe here */
00204     template = (char *) malloc( sizeof ( char ) * ( strlen( tmpdir ) + strlen( tmpname ) + 2 ) );
00205     strcpy( template, tmpdir );
00206 #if defined ( MSDOS ) || defined ( WIN32 )
00207     strcat( template, "\\" );
00208 #else
00209     strcat( template, "/" );
00210 #endif
00211     strcat( template, tmpname );
00212 
00213 #ifdef PL_HAVE_MKSTEMP
00214     fd = fdopen( mkstemp( template ), "wb+" );
00215     if ( fd == NULL )
00216     {
00217         plwarn( "pl_create_tempfile: Unable to open temporary file - returning" );
00218         if ( fname != NULL )
00219             *fname = NULL;
00220         free( template );
00221         return NULL;
00222     }
00223     /* If we are not returning the file name then unlink the file so it is
00224      * automatically deleted. */
00225 #ifdef PL_HAVE_UNLINK
00226     if ( fname == NULL )
00227         unlink( template );
00228 #endif
00229 #else
00230 #if !defined ( _S_IREAD )
00231 #define _S_IREAD     256
00232 #endif
00233 #if !defined ( _S_IWRITE )
00234 #define _S_IWRITE    128
00235 #endif
00236     fd    = NULL;
00237     flags = O_RDWR | O_BINARY | O_CREAT | O_EXCL | _O_SHORT_LIVED;
00238     /* If we are not returning the file name then add flag to automatically
00239      * delete file once all file handles are closed. */
00240     if ( fname == NULL )
00241         flags = flags | _O_TEMPORARY;
00242     mktemp( template );
00243     fd = fdopen( open( template, flags, _S_IREAD | _S_IWRITE ), "wb+" );
00244 #endif
00245 
00246     if ( fname != NULL )
00247     {
00248         *fname = template;
00249     }
00250     else
00251     {
00252         free( template );
00253     }
00254 
00255     return fd;
00256 }
00257 
 All Data Structures Files Functions