summaryrefslogtreecommitdiff
path: root/newlib/libc/stdio/tmpnam.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/stdio/tmpnam.c')
-rw-r--r--newlib/libc/stdio/tmpnam.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/newlib/libc/stdio/tmpnam.c b/newlib/libc/stdio/tmpnam.c
new file mode 100644
index 00000000000..28b394f108b
--- /dev/null
+++ b/newlib/libc/stdio/tmpnam.c
@@ -0,0 +1,208 @@
+/*
+ * tmpname.c
+ * Original Author: G. Haley
+ */
+
+/*
+FUNCTION
+<<tmpnam>>, <<tempnam>>---name for a temporary file
+
+INDEX
+ tmpnam
+INDEX
+ tempnam
+INDEX
+ _tmpnam_r
+INDEX
+ _tempnam_r
+
+ANSI_SYNOPSIS
+ #include <stdio.h>
+ char *tmpnam(char *<[s]>);
+ char *tempnam(char *<[dir]>, char *<[pfx]>);
+ char *_tmpnam_r(void *<[reent]>, char *<[s]>);
+ char *_tempnam_r(void *<[reent]>, char *<[dir]>, char *<[pfx]>);
+
+TRAD_SYNOPSIS
+ #include <stdio.h>
+ char *tmpnam(<[s]>)
+ char *<[s]>;
+
+ char *tempnam(<[dir]>, <[pfx]>)
+ char *<[dir]>;
+ char *<[pfx]>;
+
+ char *_tmpnam_r(<[reent]>, <[s]>)
+ char *<[reent]>;
+ char *<[s]>;
+
+ char *_tempnam_r(<[reent]>, <[dir]>, <[pfx]>)
+ char *<[reent]>;
+ char *<[dir]>;
+ char *<[pfx]>;
+
+DESCRIPTION
+Use either of these functions to generate a name for a temporary file.
+The generated name is guaranteed to avoid collision with other files
+(for up to <<TMP_MAX>> calls of either function).
+
+<<tmpnam>> generates file names with the value of <<P_tmpdir>>
+(defined in `<<stdio.h>>') as the leading directory component of the path.
+
+You can use the <<tmpnam>> argument <[s]> to specify a suitable area
+of memory for the generated filename; otherwise, you can call
+<<tmpnam(NULL)>> to use an internal static buffer.
+
+<<tempnam>> allows you more control over the generated filename: you
+can use the argument <[dir]> to specify the path to a directory for
+temporary files, and you can use the argument <[pfx]> to specify a
+prefix for the base filename.
+
+If <[dir]> is <<NULL>>, <<tempnam>> will attempt to use the value of
+environment variable <<TMPDIR>> instead; if there is no such value,
+<<tempnam>> uses the value of <<P_tmpdir>> (defined in `<<stdio.h>>').
+
+If you don't need any particular prefix to the basename of temporary
+files, you can pass <<NULL>> as the <[pfx]> argument to <<tempnam>>.
+
+<<_tmpnam_r>> and <<_tempnam_r>> are reentrant versions of <<tmpnam>>
+and <<tempnam>> respectively. The extra argument <[reent]> is a
+pointer to a reentrancy structure.
+
+WARNINGS
+The generated filenames are suitable for temporary files, but do not
+in themselves make files temporary. Files with these names must still
+be explicitly removed when you no longer want them.
+
+If you supply your own data area <[s]> for <<tmpnam>>, you must ensure
+that it has room for at least <<L_tmpnam>> elements of type <<char>>.
+
+RETURNS
+Both <<tmpnam>> and <<tempnam>> return a pointer to the newly
+generated filename.
+
+PORTABILITY
+ANSI C requires <<tmpnam>>, but does not specify the use of
+<<P_tmpdir>>. The System V Interface Definition (Issue 2) requires
+both <<tmpnam>> and <<tempnam>>.
+
+Supporting OS subroutines required: <<close>>, <<fstat>>, <<getpid>>,
+<<isatty>>, <<lseek>>, <<open>>, <<read>>, <<sbrk>>, <<write>>.
+
+The global pointer <<environ>> is also required.
+*/
+
+#include <_ansi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <reent.h>
+#include <errno.h>
+
+/* Try to open the file specified, if it can't be opened then try
+ another one. Return nonzero if successful, otherwise zero. */
+
+static int
+worker (ptr, result, part1, part2, part3, part4)
+ struct _reent *ptr;
+ char *result;
+ _CONST char *part1;
+ _CONST char *part2;
+ int part3;
+ int *part4;
+{
+ /* Generate the filename and make sure that there isn't one called
+ it already. */
+
+ while (1)
+ {
+ int t;
+ _sprintf_r (ptr, result, "%s/%s%x.%x", part1, part2, part3, *part4);
+ (*part4)++;
+ t = _open_r (ptr, result, O_RDONLY, 0);
+ if (t == -1)
+ {
+ if (ptr->_errno == ENOSYS)
+ {
+ result[0] = '\0';
+ return 0;
+ }
+ break;
+ }
+ _close_r (ptr, t);
+ }
+ return 1;
+}
+
+char *
+_DEFUN (_tmpnam_r, (p, s),
+ struct _reent *p _AND
+ char *s)
+{
+ char *result;
+ int pid;
+
+ if (s == NULL)
+ {
+ /* ANSI states we must use an internal static buffer if s is NULL */
+ result = p->_emergency;
+ }
+ else
+ {
+ result = s;
+ }
+ pid = _getpid_r (p);
+
+ if (worker (p, result, P_tmpdir, "t", pid, &p->_inc))
+ {
+ p->_inc++;
+ return result;
+ }
+
+ return NULL;
+}
+
+char *
+_DEFUN (_tempnam_r, (p, dir, pfx),
+ struct _reent *p _AND
+ _CONST char *dir _AND
+ _CONST char *pfx)
+{
+ char *filename;
+ int length;
+ _CONST char *prefix = (pfx) ? pfx : "";
+ if (dir == NULL && (dir = getenv ("TMPDIR")) == NULL)
+ dir = P_tmpdir;
+
+ /* two 8 digit numbers + . / */
+ length = strlen (dir) + strlen (prefix) + (4 * sizeof (int)) + 2 + 1;
+
+ filename = _malloc_r (p, length);
+ if (filename)
+ {
+ if (! worker (p, filename, dir, prefix,
+ _getpid_r (p) ^ (int) (_POINTER_INT) p, &p->_inc))
+ return NULL;
+ }
+ return filename;
+}
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN (tempnam, (dir, pfx),
+ _CONST char *dir _AND
+ _CONST char *pfx)
+{
+ return _tempnam_r (_REENT, dir, pfx);
+}
+
+char *
+_DEFUN (tmpnam, (s),
+ char *s)
+{
+ return _tmpnam_r (_REENT, s);
+}
+
+#endif