mktemp.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
  2. /* Changes: Removed mktemp */
  3. /* $OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */
  4. /*
  5. * Copyright (c) 1996-1998, 2008 Theo de Raadt
  6. * Copyright (c) 1997, 2008-2009 Todd C. Miller
  7. *
  8. * Permission to use, copy, modify, and distribute this software for any
  9. * purpose with or without fee is hereby granted, provided that the above
  10. * copyright notice and this permission notice appear in all copies.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  13. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  15. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  16. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  17. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  18. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  19. */
  20. /* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */
  21. #include "includes.h"
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <errno.h>
  25. #include <fcntl.h>
  26. #include <limits.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <ctype.h>
  31. #include <unistd.h>
  32. #if !defined(HAVE_MKDTEMP)
  33. #define MKTEMP_NAME 0
  34. #define MKTEMP_FILE 1
  35. #define MKTEMP_DIR 2
  36. #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
  37. #define NUM_CHARS (sizeof(TEMPCHARS) - 1)
  38. static int
  39. mktemp_internal(char *path, int slen, int mode)
  40. {
  41. char *start, *cp, *ep;
  42. const char *tempchars = TEMPCHARS;
  43. unsigned int r, tries;
  44. struct stat sb;
  45. size_t len;
  46. int fd;
  47. len = strlen(path);
  48. if (len == 0 || slen < 0 || (size_t)slen >= len) {
  49. errno = EINVAL;
  50. return(-1);
  51. }
  52. ep = path + len - slen;
  53. tries = 1;
  54. for (start = ep; start > path && start[-1] == 'X'; start--) {
  55. if (tries < INT_MAX / NUM_CHARS)
  56. tries *= NUM_CHARS;
  57. }
  58. tries *= 2;
  59. do {
  60. for (cp = start; cp != ep; cp++) {
  61. r = arc4random_uniform(NUM_CHARS);
  62. *cp = tempchars[r];
  63. }
  64. switch (mode) {
  65. case MKTEMP_NAME:
  66. if (lstat(path, &sb) != 0)
  67. return(errno == ENOENT ? 0 : -1);
  68. break;
  69. case MKTEMP_FILE:
  70. fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
  71. if (fd != -1 || errno != EEXIST)
  72. return(fd);
  73. break;
  74. case MKTEMP_DIR:
  75. if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0)
  76. return(0);
  77. if (errno != EEXIST)
  78. return(-1);
  79. break;
  80. }
  81. } while (--tries);
  82. errno = EEXIST;
  83. return(-1);
  84. }
  85. #if 0
  86. char *_mktemp(char *);
  87. char *
  88. _mktemp(char *path)
  89. {
  90. if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
  91. return(NULL);
  92. return(path);
  93. }
  94. __warn_references(mktemp,
  95. "warning: mktemp() possibly used unsafely; consider using mkstemp()");
  96. char *
  97. mktemp(char *path)
  98. {
  99. return(_mktemp(path));
  100. }
  101. #endif
  102. int
  103. mkstemp(char *path)
  104. {
  105. return(mktemp_internal(path, 0, MKTEMP_FILE));
  106. }
  107. int
  108. mkstemps(char *path, int slen)
  109. {
  110. return(mktemp_internal(path, slen, MKTEMP_FILE));
  111. }
  112. char *
  113. mkdtemp(char *path)
  114. {
  115. int error;
  116. error = mktemp_internal(path, 0, MKTEMP_DIR);
  117. return(error ? NULL : path);
  118. }
  119. #endif /* !defined(HAVE_MKDTEMP) */