xref: /freebsd/contrib/mandoc/compat_mkdtemp.c (revision 6d38604fc532a3fc060788e3ce40464b46047eaf)
1*6d38604fSBaptiste Daroussin /* $Id: compat_mkdtemp.c,v 1.4 2021/09/19 15:02:55 schwarze Exp $ */
261d06d6bSBaptiste Daroussin /*
3*6d38604fSBaptiste Daroussin  * Copyright (c) 2015, 2021 Ingo Schwarze <schwarze@openbsd.org>
461d06d6bSBaptiste Daroussin  *
561d06d6bSBaptiste Daroussin  * Permission to use, copy, modify, and distribute this software for any
661d06d6bSBaptiste Daroussin  * purpose with or without fee is hereby granted, provided that the above
761d06d6bSBaptiste Daroussin  * copyright notice and this permission notice appear in all copies.
861d06d6bSBaptiste Daroussin  *
961d06d6bSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1061d06d6bSBaptiste Daroussin  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1161d06d6bSBaptiste Daroussin  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1261d06d6bSBaptiste Daroussin  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1361d06d6bSBaptiste Daroussin  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1461d06d6bSBaptiste Daroussin  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1561d06d6bSBaptiste Daroussin  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1661d06d6bSBaptiste Daroussin  *
1761d06d6bSBaptiste Daroussin  * The algorithm of this function is inspired by OpenBSD mkdtemp(3)
1861d06d6bSBaptiste Daroussin  * by Theo de Raadt and Todd Miller, but the code differs.
1961d06d6bSBaptiste Daroussin  */
20*6d38604fSBaptiste Daroussin #include "config.h"
2161d06d6bSBaptiste Daroussin 
2261d06d6bSBaptiste Daroussin #include <sys/stat.h>
2361d06d6bSBaptiste Daroussin #include <errno.h>
2461d06d6bSBaptiste Daroussin #include <limits.h>
2561d06d6bSBaptiste Daroussin #include <stdlib.h>
2661d06d6bSBaptiste Daroussin #include <string.h>
2761d06d6bSBaptiste Daroussin 
2861d06d6bSBaptiste Daroussin char *
mkdtemp(char * path)2961d06d6bSBaptiste Daroussin mkdtemp(char *path)
3061d06d6bSBaptiste Daroussin {
3161d06d6bSBaptiste Daroussin 	char		*start, *cp;
3261d06d6bSBaptiste Daroussin 	unsigned	 int tries;
3361d06d6bSBaptiste Daroussin 
3461d06d6bSBaptiste Daroussin 	start = strchr(path, '\0');
3561d06d6bSBaptiste Daroussin 	while (start > path && start[-1] == 'X')
3661d06d6bSBaptiste Daroussin 		start--;
3761d06d6bSBaptiste Daroussin 
3861d06d6bSBaptiste Daroussin 	for (tries = INT_MAX; tries; tries--) {
39*6d38604fSBaptiste Daroussin 		if (mktemp(path) == NULL)
4061d06d6bSBaptiste Daroussin 			return NULL;
4161d06d6bSBaptiste Daroussin 		if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) == 0)
4261d06d6bSBaptiste Daroussin 			return path;
4361d06d6bSBaptiste Daroussin 		for (cp = start; *cp != '\0'; cp++)
4461d06d6bSBaptiste Daroussin 			*cp = 'X';
45*6d38604fSBaptiste Daroussin 		if (errno != EEXIST)
46*6d38604fSBaptiste Daroussin 			return NULL;
4761d06d6bSBaptiste Daroussin 	}
4861d06d6bSBaptiste Daroussin 	errno = EEXIST;
4961d06d6bSBaptiste Daroussin 	return NULL;
5061d06d6bSBaptiste Daroussin }
51