Sync-to-go: update copyright for 2015
[s-roff.git] / src / lib-roff / tmpname.cpp
blob5e7c11c865ae3af332631c5ec8f6289bfbbb2014
1 /*@ FIXME Consider to use our own temporary file name creation!
2 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
5 * Written by Werner Lemberg (wl@gnu.org)
7 * This is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2, or (at your option) any later
10 * version.
12 * This is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with groff; see the file COPYING. If not, write to the Free Software
19 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
22 /* This file is heavily based on the function __gen_tempname() in the
23 file tempname.c which is part of the fileutils package. */
25 #include "config.h"
26 #include "lib.h"
28 #include <errno.h>
29 #include <inttypes.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <time.h>
34 #if HAVE_SYS_TIME_H
35 # include <sys/time.h>
36 #endif
38 #include "nonposix.h"
39 #include "posix.h"
41 #ifndef TMP_MAX
42 # define TMP_MAX 238328 /* FIXME lib.h! */
43 #endif
45 /* Use the widest available unsigned type if uint64_t is not
46 available. The algorithm below extracts a number less than 62**6
47 (approximately 2**35.725) from uint64_t, so ancient hosts where
48 uintmax_t is only 32 bits lose about 3.725 bits of randomness,
49 which is better than not having mkstemp at all. */
50 #if !defined UINT64_MAX && !defined uint64_t /* FIXME -> lib.h!! */
51 # define uint64_t uintmax_t
52 #endif
54 /* These are the characters used in temporary filenames. */
55 static const char letters[] =
56 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
58 int gen_tempname(char *tmpl, int dir)
60 static uint64_t value;
62 size_t len = strlen(tmpl);
63 if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
64 return -1; /* EINVAL */
66 /* This is where the Xs start. */
67 char *XXXXXX = &tmpl[len - 6];
69 /* Get some more or less random data. */
70 #if HAVE_GETTIMEOFDAY
71 timeval tv;
72 gettimeofday(&tv, NULL);
73 uint64_t random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec;
74 #else
75 uint64_t random_time_bits = time(NULL);
76 #endif
77 value += random_time_bits ^ getpid();
79 for (int count = 0; count < TMP_MAX; value += 7777, ++count) {
80 uint64_t v = value;
82 /* Fill in the random bits. */
83 XXXXXX[0] = letters[v % 62];
84 v /= 62;
85 XXXXXX[1] = letters[v % 62];
86 v /= 62;
87 XXXXXX[2] = letters[v % 62];
88 v /= 62;
89 XXXXXX[3] = letters[v % 62];
90 v /= 62;
91 XXXXXX[4] = letters[v % 62];
92 v /= 62;
93 XXXXXX[5] = letters[v % 62];
95 int fd = dir ? mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR)
96 : open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
98 if (fd >= 0)
99 return fd;
100 else if (errno != EEXIST)
101 return -1;
104 /* We got out of the loop because we ran out of combinations to try. */
105 return -1; /* EEXIST */
108 // s-it2-mode