/* * Copyright (C) 1996-2017 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ /* A reasonably functional tmpnam. */ /* Originally by Tom Hageman, tom@basil.icce.rug.nl */ /* * This tmpnam() was changed by Gerben_Wierda@RnA.nl to serve as * tempnam() for squid-1.1.6. It ignores the directory parameter, every * temp file is written in /tmp. */ #include "squid.h" #include "compat/tempnam.h" #if HAVE_LIBC_H #include #endif #if HAVE_LIMITS_H #include #endif #if HAVE_UNISTD_H #include #endif #undef TMP_MAX #define _tmp "/tmp/" #define lengthof_tmp 5 #ifndef LONG_BIT #define LONG_BIT (CHAR_BIT * 4) /* assume sizeof(long) == 4 */ #endif #define L_tmpmin (lengthof_tmp + 5) /* 5 chars for pid. */ #if (L_tmpnam > L_tmpmin) #if (L_tmpnam > L_tmpmin + LONG_BIT / 6) /* base 64 */ #define TMP_MAX ULONG_MAX #else #define TMP_MAX ((1L << (6 * (L_tmpnam - L_tmpmin))) - 1) #endif #else #ifndef L_tmpnam #error "tmpnam: L_tmpnam undefined" #else #error "tmpnam: L_tmpnam too small" #endif #endif static char * _tmpnam(void) { static const char digits[] = #if (L_tmpnam >= L_tmpmin + LONG_BIT / 4) "0123456789abcdef"; #define TMP_BASE 16 #else "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"; #define TMP_BASE 64 #endif static unsigned long lastcount = 0; static char buffer[L_tmpnam + 1]; char *s = buffer; unsigned long count = lastcount; pid_t pid = getpid(); if (sizeof(_tmp) - 1 != lengthof_tmp) abort(); /* Consistency error. */ for (;;) { register int i = L_tmpnam; register unsigned long c; register unsigned int p; /* Build filename. (the hard way) */ s += i; *s = '\0'; c = (count == TMP_MAX) ? 0 : ++count; do { *--s = digits[c % TMP_BASE]; c /= TMP_BASE; } while (--i > L_tmpmin); p = (unsigned int) pid; do { *--s = digits[p % 10]; p /= 10; } while (--i > lengthof_tmp); do { *--s = _tmp[--i]; } while (i > 0); /* Check that the file doesn't exist. */ if (access(s, 0) != 0) break; /* It exists; retry unless we tried them all. */ if (count == lastcount) { s = NULL; break; } } lastcount = count; return s; } char * tempnam(const char *dir, const char *pfx) { return _tmpnam(); } #ifdef TEST int main() { char *t; int n = 0; while ((t = tempnam(NULL, NULL))) { printf("%s\n", t); if (++n == 1000) break; } return 1; } #endif