| /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ |
| /* Changes: Removed mktemp */ |
| |
| /* $OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */ |
| /* |
| * Copyright (c) 1996-1998, 2008 Theo de Raadt |
| * Copyright (c) 1997, 2008-2009 Todd C. Miller |
| * |
| * Permission to use, copy, modify, and distribute this software for any |
| * purpose with or without fee is hereby granted, provided that the above |
| * copyright notice and this permission notice appear in all copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */ |
| |
| #include "includes.h" |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include <unistd.h> |
| |
| #if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) |
| |
| #define MKTEMP_NAME 0 |
| #define MKTEMP_FILE 1 |
| #define MKTEMP_DIR 2 |
| |
| #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" |
| #define NUM_CHARS (sizeof(TEMPCHARS) - 1) |
| |
| static int |
| mktemp_internal(char *path, int slen, int mode) |
| { |
| char *start, *cp, *ep; |
| const char *tempchars = TEMPCHARS; |
| unsigned int r, tries; |
| struct stat sb; |
| size_t len; |
| int fd; |
| |
| len = strlen(path); |
| if (len == 0 || slen < 0 || (size_t)slen >= len) { |
| errno = EINVAL; |
| return(-1); |
| } |
| ep = path + len - slen; |
| |
| tries = 1; |
| for (start = ep; start > path && start[-1] == 'X'; start--) { |
| if (tries < INT_MAX / NUM_CHARS) |
| tries *= NUM_CHARS; |
| } |
| tries *= 2; |
| |
| do { |
| for (cp = start; cp != ep; cp++) { |
| r = arc4random_uniform(NUM_CHARS); |
| *cp = tempchars[r]; |
| } |
| |
| switch (mode) { |
| case MKTEMP_NAME: |
| if (lstat(path, &sb) != 0) |
| return(errno == ENOENT ? 0 : -1); |
| break; |
| case MKTEMP_FILE: |
| fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); |
| if (fd != -1 || errno != EEXIST) |
| return(fd); |
| break; |
| case MKTEMP_DIR: |
| if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0) |
| return(0); |
| if (errno != EEXIST) |
| return(-1); |
| break; |
| } |
| } while (--tries); |
| |
| errno = EEXIST; |
| return(-1); |
| } |
| |
| #if 0 |
| char *_mktemp(char *); |
| |
| char * |
| _mktemp(char *path) |
| { |
| if (mktemp_internal(path, 0, MKTEMP_NAME) == -1) |
| return(NULL); |
| return(path); |
| } |
| |
| __warn_references(mktemp, |
| "warning: mktemp() possibly used unsafely; consider using mkstemp()"); |
| |
| char * |
| mktemp(char *path) |
| { |
| return(_mktemp(path)); |
| } |
| #endif |
| |
| int |
| mkstemp(char *path) |
| { |
| return(mktemp_internal(path, 0, MKTEMP_FILE)); |
| } |
| |
| int |
| mkstemps(char *path, int slen) |
| { |
| return(mktemp_internal(path, slen, MKTEMP_FILE)); |
| } |
| |
| char * |
| mkdtemp(char *path) |
| { |
| int error; |
| |
| error = mktemp_internal(path, 0, MKTEMP_DIR); |
| return(error ? NULL : path); |
| } |
| |
| #endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */ |