1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright © 2022 Keith Packard
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. Neither the name of the copyright holder nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #define _DEFAULT_SOURCE
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #define check(condition, message) do { \
41 if (!(condition)) { \
42 printf("%s: %s\n", message, #condition); \
43 if (f) \
44 fclose(f); \
45 (void) remove(template); \
46 exit(1); \
47 } \
48 } while(0)
49
50 static const char NAME_TEMPLATE[] = "foo-XXXXXX";
51
52 static const char NAME_TEMPLATE_EXT[] = "foo-XXXXXX.txt";
53
54 #define EXT_LEN 4
55
56 #define MESSAGE "hello, world\n"
57
58 void
check_contents(char * template,int repeats)59 check_contents(char *template,int repeats)
60 {
61 FILE *f;
62 char *s;
63 int r;
64 int c;
65
66 f = fopen(template, "r");
67 check(f != NULL, "fopen r");
68 for (r = 0; r < repeats; r++) {
69 for (s = MESSAGE; *s; s++) {
70 c = getc(f);
71 check((char) c == *s, "contents");
72 }
73 }
74 c = getc(f);
75 check(c == EOF, "EOF");
76 r = fclose(f);
77 f = NULL;
78 check(r == 0, "fclose r");
79 }
80
81 /* Allow testing mktemp which is deprecated (for good reason) */
82 #pragma GCC diagnostic ignored "-Wpragmas"
83 #pragma GCC diagnostic ignored "-Wunknown-warning-option"
84 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
85
86 int
main(void)87 main(void)
88 {
89 char template[sizeof(NAME_TEMPLATE_EXT)];
90 char *s_ret;
91 FILE *f = NULL;
92 int i_ret;
93
94 /* Create temp file */
95 strcpy(template, NAME_TEMPLATE);
96 s_ret = mktemp(template);
97 check(s_ret == template, "mktemp");
98
99 /* Make sure we can create a file, write contents and read them back */
100 f = fopen(template, "w");
101 check(f != NULL, "fopen w");
102 fputs(MESSAGE, f);
103 fclose(f);
104 f = NULL;
105 check_contents(template, 1);
106 (void) remove(template);
107
108 /* Create temp file */
109 strcpy(template, NAME_TEMPLATE);
110 i_ret = mkstemp(template);
111 check(i_ret >= 0, "mkstemp");
112
113 /* Make sure we can create a file, write contents and read them back */
114 f = fdopen(i_ret, "w");
115 check(f != NULL, "fopen w");
116 fputs(MESSAGE, f);
117 fclose(f);
118 f = NULL;
119 check_contents(template, 1);
120 (void) remove(template);
121
122 /* Create temp file with extension */
123 strcpy(template, NAME_TEMPLATE_EXT);
124 i_ret = mkstemps(template, EXT_LEN);
125 check(i_ret >= 0, "mkstemps");
126
127 /* Make sure the name still ends with the extension */
128 check(strcmp(template + sizeof(NAME_TEMPLATE_EXT) - EXT_LEN,
129 NAME_TEMPLATE_EXT + sizeof(NAME_TEMPLATE_EXT) - EXT_LEN) == 0, "extension");
130 f = fdopen(i_ret, "w");
131 check(f != NULL, "fopen w");
132 fputs(MESSAGE, f);
133 fclose(f);
134 check_contents(template, 1);
135 (void) remove(template);
136
137 exit(0);
138 }
139