mkstemp.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* Copyright (C) 1991, 1992, 1996, 1998, 2001 Free Software Foundation, Inc.
  2. This file is derived from mkstemps.c from the GNU Libiberty Library
  3. which in turn is derived from the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8. The GNU C Library 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 GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If not,
  14. write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. As a special exception, the Free Software Foundation gives permission
  17. for additional uses of the text contained in its release of GUILE.
  18. The exception is that, if you link the GUILE library with other files
  19. to produce an executable, this does not by itself cause the
  20. resulting executable to be covered by the GNU General Public License.
  21. Your use of that executable is in no way restricted on account of
  22. linking the GUILE library code into it.
  23. This exception does not however invalidate any other reasons why
  24. the executable file might be covered by the GNU General Public License.
  25. This exception applies only to the code released by the
  26. Free Software Foundation under the name GUILE. If you copy
  27. code from other Free Software Foundation releases into a copy of
  28. GUILE, as the General Public License permits, the exception does
  29. not apply to the code that you add in this way. To avoid misleading
  30. anyone as to the status of such modified files, you must delete
  31. this exception notice from them.
  32. If you write modifications of your own for GUILE, it is your choice
  33. whether to permit this exception to apply to your modifications.
  34. If you do not wish that, delete this exception notice. */
  35. #include "libguile/scmconfig.h"
  36. #ifdef HAVE_STDLIB_H
  37. #include <stdlib.h>
  38. #endif
  39. #ifdef HAVE_STRING_H
  40. #include <string.h>
  41. #endif
  42. #include <errno.h>
  43. #include <stdio.h>
  44. #include <fcntl.h>
  45. #ifdef HAVE_UNISTD_H
  46. #include <unistd.h>
  47. #endif
  48. #ifdef HAVE_SYS_TIME_H
  49. #include <sys/time.h>
  50. #endif
  51. /* We need to provide a type for gcc_uint64_t. */
  52. #ifdef __GNUC__
  53. typedef unsigned long long gcc_uint64_t;
  54. #else
  55. typedef unsigned long gcc_uint64_t;
  56. #endif
  57. #ifndef TMP_MAX
  58. #define TMP_MAX 16384
  59. #endif
  60. /* Generate a unique temporary file name from TEMPLATE.
  61. TEMPLATE has the form:
  62. <path>/ccXXXXXX
  63. The last six characters of TEMPLATE must be "XXXXXX"; they are
  64. replaced with a string that makes the filename unique.
  65. Returns a file descriptor open on the file for reading and writing. */
  66. int
  67. mkstemp (template)
  68. char *template;
  69. {
  70. static const char letters[]
  71. = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  72. static gcc_uint64_t value;
  73. #ifdef HAVE_GETTIMEOFDAY
  74. struct timeval tv;
  75. #endif
  76. char *XXXXXX;
  77. size_t len;
  78. int count;
  79. len = strlen (template);
  80. if ((int) len < 6
  81. || strncmp (&template[len - 6], "XXXXXX", 6))
  82. {
  83. return -1;
  84. }
  85. XXXXXX = &template[len - 6];
  86. #ifdef HAVE_GETTIMEOFDAY
  87. /* Get some more or less random data. */
  88. gettimeofday (&tv, NULL);
  89. value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
  90. #else
  91. value += getpid ();
  92. #endif
  93. for (count = 0; count < TMP_MAX; ++count)
  94. {
  95. gcc_uint64_t v = value;
  96. int fd;
  97. /* Fill in the random bits. */
  98. XXXXXX[0] = letters[v % 62];
  99. v /= 62;
  100. XXXXXX[1] = letters[v % 62];
  101. v /= 62;
  102. XXXXXX[2] = letters[v % 62];
  103. v /= 62;
  104. XXXXXX[3] = letters[v % 62];
  105. v /= 62;
  106. XXXXXX[4] = letters[v % 62];
  107. v /= 62;
  108. XXXXXX[5] = letters[v % 62];
  109. fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600);
  110. if (fd >= 0)
  111. /* The file does not exist. */
  112. return fd;
  113. /* This is a random value. It is only necessary that the next
  114. TMP_MAX values generated by adding 7777 to VALUE are different
  115. with (module 2^32). */
  116. value += 7777;
  117. }
  118. /* We return the null string if we can't find a unique file name. */
  119. template[0] = '\0';
  120. return -1;
  121. }