SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
tmpname.c
Go to the documentation of this file.
1/**
2 * @file tmpname.c
3 * @brief Provides functions to generate unique temporary filenames.
4 *
5 * @copyright
6 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
7 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
8 *
9 * @license
10 * This file is distributed under the terms of the Software License Agreement
11 * found in the file LICENSE included with this distribution.
12 *
13 * @author M. Borland, C Saunders, R. Soliday
14 */
15
16#include "mdb.h"
17#include "mdb_thread.h"
18#include <time.h>
19#if defined(_WIN32)
20# include <process.h>
21#else
22# include <unistd.h>
23#endif
24
25static MDB_THREAD_LOCK tmpname_lock = MDB_THREAD_LOCK_INITIALIZER;
26
27/**
28 * @brief Supplies a unique temporary filename.
29 *
30 * Generates a unique temporary filename by appending the process ID and an incrementing
31 * counter to a base name. Ensures that the filename does not already exist.
32 *
33 * @param s Pointer to a buffer where the temporary filename will be stored. If NULL,
34 * the function allocates memory for the filename.
35 * @return A pointer to the unique temporary filename string.
36 */
37char *tmpname(s) char *s;
38{
39 static long i = 1;
40 static long pid = -1;
41 if (s == NULL)
42 s = tmalloc((unsigned)(40 * sizeof(*s)));
43 mdb_thread_lock(&tmpname_lock);
44 if (pid < 0)
45#if !defined(vxWorks)
46 pid = getpid();
47#endif
48 do {
49#if defined(vxWorks)
50 sprintf(s, "tmp.%ld", i);
51#else
52 sprintf(s, "tmp%ld.%ld", pid, i);
53#endif
54 i += 1;
55 if (!fexists(s)) {
56 mdb_thread_unlock(&tmpname_lock);
57 break;
58 }
59 } while (1);
60 return (s);
61}
62
63#include <errno.h>
64#if _LIBC
65# define struct_stat64 struct stat64
66#else
67# define struct_stat64 struct stat
68# define __getpid getpid
69# ifdef _WIN32
70# define __lxstat64(version, path, buf) stat(path, buf)
71# else
72# define __lxstat64(version, path, buf) lstat(path, buf)
73# endif
74#endif
75#ifndef __set_errno
76# define __set_errno(Val) errno = (Val)
77#endif
78
79/**
80 * @brief Generates a unique temporary filename based on a template.
81 *
82 * Replaces the last six characters ('XXXXXX') of the template with random characters
83 * from a predefined set to create a unique temporary filename. It ensures that the
84 * generated filename does not already exist by checking the filesystem.
85 *
86 * @param template A string containing the template for the temporary filename.
87 * The last six characters should be 'XXXXXX'.
88 * @return A pointer to the modified template with the unique temporary filename.
89 * If no unique name could be generated, the first character of the template is set to null.
90 */
91char *mktempOAG(char *template) {
92 int len, pid;
93 char *XXXXXX;
94 static uint64_t value;
95 uint64_t random_time_bits;
96 unsigned int count;
97 int save_errno = errno;
98 struct_stat64 st;
99 static const char letters[] =
100 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
101
102#define ATTEMPTS_MIN (62 * 62 * 62)
103
104#if ATTEMPTS_MIN < TMP_MAX
105 unsigned int attempts = TMP_MAX;
106#else
107 unsigned int attempts = ATTEMPTS_MIN;
108#endif
109
110 len = strlen(template);
111 if (len < 6 || memcmp(&template[len - 6], "XXXXXX", 6)) {
112 template[0] = '\0';
113 return (template);
114 }
115
116 /* This is where the Xs start. */
117 XXXXXX = &template[len - 6];
118
119 /* Get some more or less random data. */
120 random_time_bits = time(NULL);
121
122 pid = __getpid();
123 mdb_thread_lock(&tmpname_lock);
124 value += random_time_bits ^ (pid * pid);
125 for (count = 0; count < attempts; value += 7777, ++count) {
126 uint64_t v = value;
127
128 /* Fill in the random bits. */
129 XXXXXX[0] = letters[v % 62];
130 v /= 31;
131 XXXXXX[1] = letters[v % 62];
132 v /= 31;
133 XXXXXX[2] = letters[v % 62];
134 v /= 31;
135 XXXXXX[3] = letters[v % 62];
136 v /= 31;
137 XXXXXX[4] = letters[v % 62];
138 v /= 31;
139 XXXXXX[5] = letters[v % 62];
140
141#if defined(vxWorks)
142 if (!fexists(template) < 0) {
143 mdb_thread_unlock(&tmpname_lock);
144 return (template);
145 }
146#else
147 if (__lxstat64(_STAT_VER, template, &st) < 0) {
148 if (errno == ENOENT) {
149 __set_errno(save_errno);
150 mdb_thread_unlock(&tmpname_lock);
151 return (template);
152 } else {
153 /* Give up now. */
154 template[0] = '\0';
155 mdb_thread_unlock(&tmpname_lock);
156 return (template);
157 }
158 }
159#endif
160 }
161
162 /* We got out of the loop because we ran out of combinations to try. */
163 template[0] = '\0';
164 mdb_thread_unlock(&tmpname_lock);
165 return (template);
166}
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:65
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
char * tmpname(char *s)
Supplies a unique temporary filename.
Definition tmpname.c:37
char * mktempOAG(char *template)
Generates a unique temporary filename based on a template.
Definition tmpname.c:91