x86: Set default non_temporal_threshold for Zhaoxin processors
[glibc.git] / support / temp_file.c
blob28a0043683547f1d27da9d4fd600ce786dd7a464
1 /* Temporary file handling for tests.
2 Copyright (C) 1998-2024 Free Software Foundation, Inc.
3 Copyright The GNU Tools Authors.
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <https://www.gnu.org/licenses/>. */
20 /* This is required to get an mkstemp which can create large files on
21 some 32-bit platforms. */
22 #define _FILE_OFFSET_BITS 64
24 #include <support/check.h>
25 #include <support/temp_file.h>
26 #include <support/temp_file-internal.h>
27 #include <support/support.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <paths.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <xunistd.h>
37 /* List of temporary files. */
38 static struct temp_name_list
40 struct temp_name_list *next;
41 char *name;
42 pid_t owner;
43 bool toolong;
44 } *temp_name_list;
46 /* Location of the temporary files. Set by the test skeleton via
47 support_set_test_dir. The string is not be freed. */
48 static const char *test_dir = _PATH_TMP;
50 /* Name of subdirectories in a too long temporary directory tree. */
51 static char toolong_subdir[NAME_MAX + 1];
52 static bool toolong_initialized;
53 static size_t toolong_path_max;
55 static void
56 add_temp_file_internal (const char *name, bool toolong)
58 struct temp_name_list *newp
59 = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
60 char *newname = strdup (name);
61 if (newname != NULL)
63 newp->name = newname;
64 newp->next = temp_name_list;
65 newp->owner = getpid ();
66 newp->toolong = toolong;
67 temp_name_list = newp;
69 else
70 free (newp);
73 void
74 add_temp_file (const char *name)
76 add_temp_file_internal (name, false);
79 int
80 create_temp_file_in_dir (const char *base, const char *dir, char **filename)
82 char *fname;
83 int fd;
85 fname = xasprintf ("%s/%sXXXXXX", dir, base);
87 fd = mkstemp (fname);
88 if (fd == -1)
90 printf ("cannot open temporary file '%s': %m\n", fname);
91 free (fname);
92 return -1;
95 add_temp_file (fname);
96 if (filename != NULL)
97 *filename = fname;
98 else
99 free (fname);
101 return fd;
105 create_temp_file (const char *base, char **filename)
107 return create_temp_file_in_dir (base, test_dir, filename);
110 static char *
111 create_temp_directory_internal (const char *base, bool toolong)
113 char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
114 if (mkdtemp (path) == NULL)
116 printf ("error: mkdtemp (\"%s\"): %m", path);
117 exit (1);
119 add_temp_file_internal (path, toolong);
120 return path;
123 char *
124 support_create_temp_directory (const char *base)
126 return create_temp_directory_internal (base, false);
129 static void
130 ensure_toolong_initialized (void)
132 if (!toolong_initialized)
133 FAIL_EXIT1 ("uninitialized toolong directory tree\n");
136 static void
137 initialize_toolong (const char *base)
139 long name_max = pathconf (base, _PC_NAME_MAX);
140 name_max = (name_max < 0 ? 64
141 : (name_max < sizeof (toolong_subdir) ? name_max
142 : sizeof (toolong_subdir) - 1));
144 long path_max = pathconf (base, _PC_PATH_MAX);
145 path_max = (path_max < 0 ? 1024
146 : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX);
148 /* Sanity check to ensure that the test does not create temporary directories
149 in different filesystems because this API doesn't support it. */
150 if (toolong_initialized)
152 if (name_max != strlen (toolong_subdir))
153 FAIL_UNSUPPORTED ("name_max: Temporary directories in different"
154 " filesystems not supported yet\n");
155 if (path_max != toolong_path_max)
156 FAIL_UNSUPPORTED ("path_max: Temporary directories in different"
157 " filesystems not supported yet\n");
158 return;
161 toolong_path_max = path_max;
163 size_t len = name_max;
164 memset (toolong_subdir, 'X', len);
165 toolong_initialized = true;
168 char *
169 support_create_and_chdir_toolong_temp_directory (const char *basename)
171 char *base = create_temp_directory_internal (basename, true);
172 xchdir (base);
174 initialize_toolong (base);
176 size_t sz = strlen (toolong_subdir);
178 /* Create directories and descend into them so that the final path is larger
179 than PATH_MAX. */
180 for (size_t i = 0; i <= toolong_path_max / sz; i++)
182 int ret = mkdir (toolong_subdir, S_IRWXU);
183 if (ret != 0 && errno == ENAMETOOLONG)
184 FAIL_UNSUPPORTED ("Filesystem does not support creating too long "
185 "directory trees\n");
186 else if (ret != 0)
187 FAIL_EXIT1 ("Failed to create directory tree: %m\n");
188 xchdir (toolong_subdir);
190 return base;
193 void
194 support_chdir_toolong_temp_directory (const char *base)
196 ensure_toolong_initialized ();
198 xchdir (base);
200 size_t sz = strlen (toolong_subdir);
201 for (size_t i = 0; i <= toolong_path_max / sz; i++)
202 xchdir (toolong_subdir);
205 /* Helper functions called by the test skeleton follow. */
207 static void
208 remove_toolong_subdirs (const char *base)
210 ensure_toolong_initialized ();
212 if (chdir (base) != 0)
214 printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n",
215 base);
216 return;
219 /* Descend. */
220 int levels = 0;
221 size_t sz = strlen (toolong_subdir);
222 for (levels = 0; levels <= toolong_path_max / sz; levels++)
223 if (chdir (toolong_subdir) != 0)
225 printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n",
226 toolong_subdir);
227 break;
230 /* Ascend and remove. */
231 while (--levels >= 0)
233 if (chdir ("..") != 0)
235 printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n");
236 return;
238 if (remove (toolong_subdir) != 0)
240 printf ("warning: could not remove subdirectory: %s: %m\n",
241 toolong_subdir);
242 return;
247 void
248 support_delete_temp_files (void)
250 pid_t pid = getpid ();
251 while (temp_name_list != NULL)
253 /* Only perform the removal if the path was registered in the same
254 process, as identified by the PID. (This assumes that the
255 parent process which registered the temporary file sticks
256 around, to prevent PID reuse.) */
257 if (temp_name_list->owner == pid)
259 if (temp_name_list->toolong)
260 remove_toolong_subdirs (temp_name_list->name);
262 if (remove (temp_name_list->name) != 0)
263 printf ("warning: could not remove temporary file: %s: %m\n",
264 temp_name_list->name);
266 free (temp_name_list->name);
268 struct temp_name_list *next = temp_name_list->next;
269 free (temp_name_list);
270 temp_name_list = next;
274 void
275 support_print_temp_files (FILE *f)
277 if (temp_name_list != NULL)
279 struct temp_name_list *n;
280 fprintf (f, "temp_files=(\n");
281 for (n = temp_name_list; n != NULL; n = n->next)
282 fprintf (f, " '%s'\n", n->name);
283 fprintf (f, ")\n");
287 void
288 support_set_test_dir (const char *path)
290 test_dir = path;