diff options
Diffstat (limited to 'src/libs/file/temp.c')
-rw-r--r-- | src/libs/file/temp.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/libs/file/temp.c b/src/libs/file/temp.c new file mode 100644 index 0000000..3253e0d --- /dev/null +++ b/src/libs/file/temp.c @@ -0,0 +1,199 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Contains code handling temporary files and dirs + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#ifdef WIN32 +# include <io.h> +#endif +#include <string.h> +#include <time.h> +#include "filintrn.h" +#include "libs/timelib.h" +#include "port.h" +#include "libs/compiler.h" +#include "libs/log.h" +#include "libs/memlib.h" + +static char *tempDirName; +uio_DirHandle *tempDir; + +static void +removeTempDir (void) +{ + rmdir (tempDirName); +} + +// Try if the null-terminated path 'dir' to a directory is valid +// as temp path. +// On success, 'buf' will be filled with the path, with a trailing /, +// null-terminated, and 0 is returned. +// On failure, EINVAL, ENAMETOOLONG, or one of the errors access() can return +// is returned, and the contents of buf is unspecified. +static int +tryTempDir (char *buf, size_t buflen, const char *dir) +{ + size_t len; + int haveSlash; + + if (dir == NULL) + return EINVAL; + + if (dir[0] == '\0') + return EINVAL; + + len = strlen (dir); + haveSlash = (dir[len - 1] == '/' +#ifdef WIN32 + || dir[len - 1] == '\\' +#endif + ); + if ((haveSlash ? len : len + 1) >= buflen) + return ENAMETOOLONG; + + strcpy (buf, dir); +#if 0 + //def WIN32 + { + char *bufPtr; + for (bufPtr = buf; *bufPtr != '\0'; bufPtr++) + { + if (*bufPtr == '\\') + *bufPtr = '/'; + } + } +#endif + if (!haveSlash) + { + buf[len] = '/'; + len++; + buf[len] = '\0'; + } + if (access (buf, R_OK | W_OK) == -1) + return errno; + + return 0; +} + +static void +getTempDir (char *buf, size_t buflen) { + char cwd[PATH_MAX]; + + if (tryTempDir (buf, buflen, getenv("TMP")) && + tryTempDir (buf, buflen, getenv("TEMP")) && +#if !defined(WIN32) || defined (__CYGWIN__) + tryTempDir (buf, buflen, "/tmp/") && + tryTempDir (buf, buflen, "/var/tmp/") && +#endif + tryTempDir (buf, buflen, getcwd (cwd, sizeof cwd))) + { + log_add (log_Fatal, "Fatal Error: Cannot find a suitable location " + "to store temporary files."); + exit (EXIT_FAILURE); + } +} + +// Sets the global var 'tempDir' +static int +mountTempDir(const char *name) { + static uio_AutoMount *autoMount[] = { NULL }; + uio_MountHandle *tempHandle; + extern uio_Repository *repository; + + tempHandle = uio_mountDir (repository, "/tmp/", + uio_FSTYPE_STDIO, NULL, NULL, name, autoMount, + uio_MOUNT_TOP, NULL); + if (tempHandle == NULL) { + int saveErrno = errno; + log_add (log_Fatal, "Fatal error: Couldn't mount temp dir '%s': " + "%s", name, strerror (errno)); + errno = saveErrno; + return -1; + } + + tempDir = uio_openDir (repository, "/tmp", 0); + if (tempDir == NULL) { + int saveErrno = errno; + log_add (log_Fatal, "Fatal error: Could not open temp dir: %s", + strerror (errno)); + errno = saveErrno; + return -1; + } + return 0; +} + +#define NUM_TEMP_RETRIES 16 + // Number of files to try to open before giving up. +void +initTempDir (void) { + size_t len; + DWORD num; + int i; + char *tempPtr; + // Pointer to the location in the tempDirName string where the + // path to the temp dir ends and the dir starts. + + tempDirName = HMalloc (PATH_MAX); + getTempDir (tempDirName, PATH_MAX - 21); + // reserve 8 chars for dirname, 1 for slash, and 12 for filename + len = strlen(tempDirName); + + num = ((DWORD) time (NULL)); +// num = GetTimeCounter () % 0xffffffff; + tempPtr = tempDirName + len; + for (i = 0; i < NUM_TEMP_RETRIES; i++) + { + sprintf (tempPtr, "%08x", num + i); + if (createDirectory (tempDirName, 0700) == -1) + continue; + + // Success, we've got a temp dir. + tempDirName = HRealloc (tempDirName, len + 9); + atexit (removeTempDir); + if (mountTempDir (tempDirName) == -1) + exit (EXIT_FAILURE); + return; + } + + // Failure, could not make a temporary directory. + log_add (log_Fatal, "Fatal error: Cannot get a name for a temporary " + "directory."); + exit (EXIT_FAILURE); +} + +void +unInitTempDir (void) { + uio_closeDir(tempDir); + // the removing of the dir is handled via atexit +} + +// return the path to a file in the temp dir with the specified filename. +// returns a pointer to a static buffer. +char * +tempFilePath (const char *filename) { + static char file[PATH_MAX]; + + if (snprintf (file, PATH_MAX, "%s/%s", tempDirName, filename) == -1) { + log_add (log_Fatal, "Path to temp file too long."); + exit (EXIT_FAILURE); + } + return file; +} + + |