PLplot 5.9.6
|
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