Mercurial > hg > minc-tools
changeset 1528:010f0aaadbd3
Added micreate_tempfile() to resolve issues with tempfile naming and creation, especially to suppress those annoying GNU linker messages about tempnam() and tmpnam().
author | bert <bert> |
---|---|
date | Mon, 17 Mar 2003 16:15:33 +0000 (2003-03-17) |
parents | f6f01efdca4b |
children | d2ffce2e3b0c |
files | libsrc/netcdf_convenience.c |
diffstat | 1 files changed, 109 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/libsrc/netcdf_convenience.c +++ b/libsrc/netcdf_convenience.c @@ -29,13 +29,17 @@ micopy_var_values micopy_all_var_defs micopy_all_var_values + micreate_tempfile private : execute_decompress_command MI_vcopy_action @CREATED : July 27, 1992. (Peter Neelin, Montreal Neurological Institute) @MODIFIED : * $Log: netcdf_convenience.c,v $ - * Revision 6.7 2001-08-20 13:19:15 neelin + * Revision 6.8 2003-03-17 16:15:33 bert + * Added micreate_tempfile() to resolve issues with tempfile naming and creation, especially to suppress those annoying GNU linker messages about tempnam() and tmpnam(). + * + * Revision 6.7 2001/08/20 13:19:15 neelin * Added function miattget_with_sign to allow the caller to specify the sign * of the input attribute since this information is ambiguous. This is * necessary for the valid_range attribute which should have the same sign @@ -132,13 +136,15 @@ ---------------------------------------------------------------------------- */ #ifndef lint -static char rcsid[] = "$Header: /private-cvsroot/minc/libsrc/netcdf_convenience.c,v 6.7 2001-08-20 13:19:15 neelin Exp $ MINC (MNI)"; +static char rcsid[] = "$Header: /private-cvsroot/minc/libsrc/netcdf_convenience.c,v 6.8 2003-03-17 16:15:33 bert Exp $ MINC (MNI)"; #endif +#include "config.h" /* From configure */ #include <minc_private.h> #ifdef unix #include <unistd.h> #include <sys/wait.h> +#include <sys/stat.h> /* For S_IREAD, S_IWRITE */ #endif /* Private functions */ @@ -419,7 +425,7 @@ /* Create a temporary file name */ if (tempfile == NULL) { - newfile = tempnam(NULL, NULL); + newfile = micreate_tempfile(); } else { newfile = strdup(tempfile); @@ -1523,3 +1529,103 @@ MI_RETURN(MI_NOERROR); } + + +/* ----------------------------- MNI Header ----------------------------------- +@NAME : micreate_tempfile +@INPUT : void +@OUTPUT : (none) +@RETURNS : Pointer to filename (which must be freed), or NULL if an error + occurs. +@DESCRIPTION: Creates a temporary file (which is initially CLOSED). +@METHOD : Unnecessarily convoluted, I suppose... See comments. +@GLOBALS : +@CALLS : Standard POSIX/UNIX routines +@CREATED : 07-March-2003 by bert@bic.mni.mcgill.ca +@MODIFIED : +---------------------------------------------------------------------------- */ + +/* Force P_tmpdir to be something reasonable. */ +#if !defined(P_tmpdir) +#define P_tmpdir "/var/tmp" +#endif /* P_tmpdir not defined */ + +public char * +micreate_tempfile(void) +{ + int tmp_fd; + char *tmpfile_ptr; + +#if defined (HAVE_MKSTEMP) + + /* Best-case scenario (so far...) + * mkstemp() creates a file immediately, minimizing the race + * conditions that exist when using the other functions. These race + * conditions can lead to small security holes (and large, annoying + * GNU linker messages). + * + * The only catch is that mkstemp() does not automatically put the + * file in the TMPDIR directory (or some other appropriate place). + * So I more-or-less emulate that behavior here. + */ + const char pat_str[] = "/minc-XXXXXX"; + char *tmpdir_ptr; + + if ((tmpdir_ptr = getenv("TMPDIR")) == NULL) { + tmpdir_ptr = P_tmpdir; + } + tmpfile_ptr = malloc(strlen(tmpdir_ptr) + sizeof (pat_str)); + if (tmpfile_ptr == NULL) { + return (NULL); + } + strcpy(tmpfile_ptr, tmpdir_ptr); + strcat(tmpfile_ptr, pat_str); + tmp_fd = mkstemp(tmpfile_ptr); /* Creates the file if possible. */ + +#elif defined (HAVE_TEMPNAM) + + /* Second-best case. While not completely avoiding the race condition, + * this approach should at least have the nice property of putting the + * tempfile in the right directory (on IRIX and Linux, at least - on + * some systems tempnam() may not consult the TMPDIR environment variable). + */ + tmpfile_ptr = tempnam(NULL, "minc-"); + if (tmpfile_ptr == NULL) { + return (NULL); + } + tmp_fd = open(tmpfile_ptr, O_CREAT | O_EXCL | O_RDWR, S_IWRITE | S_IREAD); + +#elif defined (HAVE_TMPNAM) + /* Worst case. tmpnam() is apparently the worst of all possible worlds + * here. It doesn't allow any way to force a particular directory, + * and it doesn't avoid the race condition. But volume_io used it for + * years, so I see no reason to disallow this case for systems that + * might not define the above two functions (whether any such systems + * exist is unclear to me). + */ + tmpfile_ptr = malloc(L_tmpnam + 1); + if (tmpfile_ptr == NULL) { + return (NULL); + } + if (tmpnam(tmpfile_ptr) == NULL) { + free(tmpfile_ptr); + return (NULL); + } + tmp_fd = open(tmpfile_ptr, O_CREAT | O_EXCL | O_RDWR, S_IWRITE | S_IREAD); + +#else +#error "System defines neither mkstemp(), tempnam(), nor tmpnam()" +#endif /* Neither HAVE_MKSTEMP, HAVE_TEMPNAM, or HAVE_TMPNAM defined. */ + + /* If we get here, tmp_fd should have been opened and the file + * created. Now go ahead and close the file. + */ + if (tmp_fd >= 0) { + close(tmp_fd); + } + else { + free(tmpfile_ptr); + tmpfile_ptr = NULL; + } + return (tmpfile_ptr); +}