tmpdir.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* Copyright (C) 1999, 2001-2002, 2006, 2009-2016 Free Software Foundation,
  2. Inc.
  3. This file is part of the GNU C Library.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. /* Extracted from sysdeps/posix/tempname.c. */
  15. #include <config.h>
  16. /* Specification. */
  17. #include "tmpdir.h"
  18. #include <stdbool.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #ifndef __set_errno
  23. # define __set_errno(Val) errno = (Val)
  24. #endif
  25. #include <stdio.h>
  26. #ifndef P_tmpdir
  27. # ifdef _P_tmpdir /* native Windows */
  28. # define P_tmpdir _P_tmpdir
  29. # else
  30. # define P_tmpdir "/tmp"
  31. # endif
  32. #endif
  33. #include <sys/stat.h>
  34. #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  35. # define WIN32_LEAN_AND_MEAN /* avoid including junk */
  36. # include <windows.h>
  37. #endif
  38. #include "pathmax.h"
  39. #if _LIBC
  40. # define struct_stat64 struct stat64
  41. #else
  42. # define struct_stat64 struct stat
  43. # define __libc_secure_getenv secure_getenv
  44. # define __xstat64(version, path, buf) stat (path, buf)
  45. #endif
  46. /* Pathname support.
  47. ISSLASH(C) tests whether C is a directory separator character.
  48. */
  49. #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
  50. /* Native Windows, Cygwin, OS/2, DOS */
  51. # define ISSLASH(C) ((C) == '/' || (C) == '\\')
  52. #else
  53. /* Unix */
  54. # define ISSLASH(C) ((C) == '/')
  55. #endif
  56. /* Return nonzero if DIR is an existent directory. */
  57. static bool
  58. direxists (const char *dir)
  59. {
  60. struct_stat64 buf;
  61. return __xstat64 (_STAT_VER, dir, &buf) == 0 && S_ISDIR (buf.st_mode);
  62. }
  63. /* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is
  64. non-null and exists, uses it; otherwise uses the first of $TMPDIR,
  65. P_tmpdir, /tmp that exists. Copies into TMPL a template suitable
  66. for use with mk[s]temp. Will fail (-1) if DIR is non-null and
  67. doesn't exist, none of the searched dirs exists, or there's not
  68. enough space in TMPL. */
  69. int
  70. path_search (char *tmpl, size_t tmpl_len, const char *dir, const char *pfx,
  71. bool try_tmpdir)
  72. {
  73. const char *d;
  74. size_t dlen, plen;
  75. bool add_slash;
  76. if (!pfx || !pfx[0])
  77. {
  78. pfx = "file";
  79. plen = 4;
  80. }
  81. else
  82. {
  83. plen = strlen (pfx);
  84. if (plen > 5)
  85. plen = 5;
  86. }
  87. if (try_tmpdir)
  88. {
  89. d = __libc_secure_getenv ("TMPDIR");
  90. if (d != NULL && direxists (d))
  91. dir = d;
  92. else if (dir != NULL && direxists (dir))
  93. /* nothing */ ;
  94. else
  95. dir = NULL;
  96. }
  97. if (dir == NULL)
  98. {
  99. #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
  100. char dirbuf[PATH_MAX];
  101. DWORD retval;
  102. /* Find Windows temporary file directory.
  103. We try this before P_tmpdir because Windows defines P_tmpdir to "\\"
  104. and will therefore try to put all temporary files in the root
  105. directory (unless $TMPDIR is set). */
  106. retval = GetTempPath (PATH_MAX, dirbuf);
  107. if (retval > 0 && retval < PATH_MAX && direxists (dirbuf))
  108. dir = dirbuf;
  109. else
  110. #endif
  111. if (direxists (P_tmpdir))
  112. dir = P_tmpdir;
  113. else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp"))
  114. dir = "/tmp";
  115. else
  116. {
  117. __set_errno (ENOENT);
  118. return -1;
  119. }
  120. }
  121. dlen = strlen (dir);
  122. #ifdef __VMS
  123. add_slash = 0;
  124. #else
  125. add_slash = dlen != 0 && !ISSLASH (dir[dlen - 1]);
  126. #endif
  127. /* check we have room for "${dir}/${pfx}XXXXXX\0" */
  128. if (tmpl_len < dlen + add_slash + plen + 6 + 1)
  129. {
  130. __set_errno (EINVAL);
  131. return -1;
  132. }
  133. memcpy (tmpl, dir, dlen);
  134. sprintf (tmpl + dlen, &"/%.*sXXXXXX"[!add_slash], (int) plen, pfx);
  135. return 0;
  136. }