Back to index

lightning-sunbird  0.9+nobinonly
mktemp.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1987, 1993
00003  *     The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. ***REMOVED*** - see 
00014  *    ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
00015  * 4. Neither the name of the University nor the names of its contributors
00016  *    may be used to endorse or promote products derived from this software
00017  *    without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00020  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00023  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00025  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00026  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00028  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  */
00031 
00032 #if defined(LIBC_SCCS) && !defined(lint)
00033 static char sccsid[] = "@(#)mktemp.c      8.1 (Berkeley) 6/4/93";
00034 #endif /* LIBC_SCCS and not lint */
00035 
00036 #include "watcomfx.h"
00037 
00038 #ifdef macintosh
00039 #include <unix.h>
00040 #else
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 #endif
00044 #include <fcntl.h>
00045 #include <errno.h>
00046 #include <stdio.h>
00047 #include <ctype.h>
00048 #include "mcom_db.h"
00049 
00050 #if !defined(_WINDOWS) && !defined(XP_OS2_VACPP)
00051 #include <unistd.h>
00052 #endif
00053 
00054 #ifdef XP_OS2_VACPP
00055 #include <process.h>
00056 #endif
00057 
00058 #ifdef _WINDOWS
00059 #include <process.h>
00060 #include "winfile.h"
00061 #endif
00062 
00063 static int _gettemp(char *path, register int *doopen, int extraFlags);
00064 
00065 int
00066 mkstemp(char *path)
00067 {
00068 #ifdef XP_OS2
00069        FILE *temp = tmpfile();
00070 
00071        return (temp ? fileno(temp) : -1);
00072 #else
00073        int fd;
00074 
00075        return (_gettemp(path, &fd, 0) ? fd : -1);
00076 #endif
00077 }
00078 
00079 int
00080 mkstempflags(char *path, int extraFlags)
00081 {
00082        int fd;
00083 
00084        return (_gettemp(path, &fd, extraFlags) ? fd : -1);
00085 }
00086 
00087 char *
00088 mktemp(char *path)
00089 {
00090        return(_gettemp(path, (int *)NULL, 0) ? path : (char *)NULL);
00091 }
00092 
00093 /* NB: This routine modifies its input string, and does not always restore it.
00094 ** returns 1 on success, 0 on failure.
00095 */
00096 static int 
00097 _gettemp(char *path, register int *doopen, int extraFlags)
00098 {    
00099 #if !defined(_WINDOWS) || defined(_WIN32)
00100        extern int errno;                    
00101 #endif
00102        register char *start, *trv;
00103        struct stat sbuf;
00104        unsigned int pid;
00105 
00106        pid = getpid();
00107        for (trv = path; *trv; ++trv);            /* extra X's get set to 0's */
00108        while (*--trv == 'X') {
00109               *trv = (pid % 10) + '0';
00110               pid /= 10;
00111        }
00112 
00113        /*
00114         * check the target directory; if you have six X's and it
00115         * doesn't exist this runs for a *very* long time.
00116         */
00117        for (start = trv + 1;; --trv) {
00118               char saved;
00119               if (trv <= path)
00120                      break;
00121               saved = *trv;
00122               if (saved == '/' || saved == '\\') {
00123                      int rv;
00124                      *trv = '\0';
00125                      rv = stat(path, &sbuf);
00126                      *trv = saved;
00127                      if (rv)
00128                             return(0);
00129                      if (!S_ISDIR(sbuf.st_mode)) {
00130                             errno = ENOTDIR;
00131                             return(0);
00132                      }
00133                      break;
00134               }
00135        }
00136 
00137        for (;;) {
00138               if (doopen) {
00139                      if ((*doopen =
00140                          open(path, O_CREAT|O_EXCL|O_RDWR|extraFlags, 0600)) >= 0)
00141                             return(1);
00142                      if (errno != EEXIST)
00143                             return(0);
00144               }
00145               else if (stat(path, &sbuf))
00146                      return(errno == ENOENT ? 1 : 0);
00147 
00148               /* tricky little algorithm for backward compatibility */
00149               for (trv = start;;) {
00150                      if (!*trv)
00151                             return(0);
00152                      if (*trv == 'z')
00153                             *trv++ = 'a';
00154                      else {
00155                             if (isdigit(*trv))
00156                                    *trv = 'a';
00157                             else
00158                                    ++*trv;
00159                             break;
00160                      }
00161               }
00162        }
00163        /*NOTREACHED*/
00164 }