Blame nss/lib/dbm/src/mktemp.c

Packit 40b132
/*
Packit 40b132
 * Copyright (c) 1987, 1993
Packit 40b132
 *	The Regents of the University of California.  All rights reserved.
Packit 40b132
 *
Packit 40b132
 * Redistribution and use in source and binary forms, with or without
Packit 40b132
 * modification, are permitted provided that the following conditions
Packit 40b132
 * are met:
Packit 40b132
 * 1. Redistributions of source code must retain the above copyright
Packit 40b132
 *    notice, this list of conditions and the following disclaimer.
Packit 40b132
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 40b132
 *    notice, this list of conditions and the following disclaimer in the
Packit 40b132
 *    documentation and/or other materials provided with the distribution.
Packit 40b132
 * 3. ***REMOVED*** - see 
Packit 40b132
 *    ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
Packit 40b132
 * 4. Neither the name of the University nor the names of its contributors
Packit 40b132
 *    may be used to endorse or promote products derived from this software
Packit 40b132
 *    without specific prior written permission.
Packit 40b132
 *
Packit 40b132
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit 40b132
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 40b132
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 40b132
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 40b132
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 40b132
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 40b132
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 40b132
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 40b132
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 40b132
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 40b132
 * SUCH DAMAGE.
Packit 40b132
 */
Packit 40b132
Packit 40b132
#if defined(LIBC_SCCS) && !defined(lint)
Packit 40b132
static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
Packit 40b132
#endif /* LIBC_SCCS and not lint */
Packit 40b132
Packit 40b132
#ifdef macintosh
Packit 40b132
#include <unix.h>
Packit 40b132
#else
Packit 40b132
#include <sys/types.h>
Packit 40b132
#include <sys/stat.h>
Packit 40b132
#endif
Packit 40b132
#include <fcntl.h>
Packit 40b132
#include <errno.h>
Packit 40b132
#include <stdio.h>
Packit 40b132
#include <ctype.h>
Packit 40b132
#include "mcom_db.h"
Packit 40b132
Packit 40b132
#ifndef _WINDOWS
Packit 40b132
#include <unistd.h>
Packit 40b132
#endif
Packit 40b132
Packit Service 2e48ff
#ifdef _WINDOWS
Packit Service 2e48ff
#include <process.h>
Packit Service 2e48ff
#include "winfile.h"
Packit Service 2e48ff
#endif
Packit Service 2e48ff
Packit 40b132
static int _gettemp(char *path, register int *doopen, int extraFlags);
Packit 40b132
Packit 40b132
int
Packit 40b132
mkstemp(char *path)
Packit 40b132
{
Packit 40b132
#ifdef XP_OS2
Packit 40b132
	FILE *temp = tmpfile();
Packit 40b132
Packit 40b132
	return (temp ? fileno(temp) : -1);
Packit 40b132
#else
Packit 40b132
	int fd;
Packit 40b132
Packit 40b132
	return (_gettemp(path, &fd, 0) ? fd : -1);
Packit 40b132
#endif
Packit 40b132
}
Packit 40b132
Packit 40b132
int
Packit 40b132
mkstempflags(char *path, int extraFlags)
Packit 40b132
{
Packit 40b132
	int fd;
Packit 40b132
Packit 40b132
	return (_gettemp(path, &fd, extraFlags) ? fd : -1);
Packit 40b132
}
Packit 40b132
Packit 40b132
/* NB: This routine modifies its input string, and does not always restore it.
Packit 40b132
** returns 1 on success, 0 on failure.
Packit 40b132
*/
Packit 40b132
static int 
Packit 40b132
_gettemp(char *path, register int *doopen, int extraFlags)
Packit 40b132
{    
Packit 40b132
	register char *start, *trv;
Packit 40b132
	struct stat sbuf;
Packit 40b132
	unsigned int pid;
Packit 40b132
Packit 40b132
	pid = getpid();
Packit 40b132
	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
Packit 40b132
	while (*--trv == 'X') {
Packit 40b132
		*trv = (pid % 10) + '0';
Packit 40b132
		pid /= 10;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/*
Packit 40b132
	 * check the target directory; if you have six X's and it
Packit 40b132
	 * doesn't exist this runs for a *very* long time.
Packit 40b132
	 */
Packit 40b132
	for (start = trv + 1;; --trv) {
Packit 40b132
		char saved;
Packit 40b132
		if (trv <= path)
Packit 40b132
			break;
Packit 40b132
		saved = *trv;
Packit 40b132
		if (saved == '/' || saved == '\\') {
Packit 40b132
			int rv;
Packit 40b132
			*trv = '\0';
Packit 40b132
			rv = stat(path, &sbuf);
Packit 40b132
			*trv = saved;
Packit 40b132
			if (rv)
Packit 40b132
				return(0);
Packit 40b132
			if (!S_ISDIR(sbuf.st_mode)) {
Packit 40b132
				errno = ENOTDIR;
Packit 40b132
				return(0);
Packit 40b132
			}
Packit 40b132
			break;
Packit 40b132
		}
Packit 40b132
	}
Packit 40b132
Packit 40b132
	for (;;) {
Packit 40b132
		if (doopen) {
Packit 40b132
			if ((*doopen =
Packit 40b132
			    open(path, O_CREAT|O_EXCL|O_RDWR|extraFlags, 0600)) >= 0)
Packit 40b132
				return(1);
Packit 40b132
			if (errno != EEXIST)
Packit 40b132
				return(0);
Packit 40b132
		}
Packit 40b132
		else if (stat(path, &sbuf))
Packit 40b132
			return(errno == ENOENT ? 1 : 0);
Packit 40b132
Packit 40b132
		/* tricky little algorithm for backward compatibility */
Packit 40b132
		for (trv = start;;) {
Packit 40b132
			if (!*trv)
Packit 40b132
				return(0);
Packit 40b132
			if (*trv == 'z')
Packit 40b132
				*trv++ = 'a';
Packit 40b132
			else {
Packit 40b132
				if (isdigit(*trv))
Packit 40b132
					*trv = 'a';
Packit 40b132
				else
Packit 40b132
					++*trv;
Packit 40b132
				break;
Packit 40b132
			}
Packit 40b132
		}
Packit 40b132
	}
Packit 40b132
	/*NOTREACHED*/
Packit 40b132
}