root/ext/zip/lib/mkstemp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _zip_mkstemp

   1 /* Adapted from NetBSB libc by Dieter Baron */
   2 
   3 /*      NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp       */
   4 
   5 /*
   6  * Copyright (c) 1987, 1993
   7  *      The Regents of the University of California.  All rights reserved.
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions
  11  * are met:
  12  * 1. Redistributions of source code must retain the above copyright
  13  *    notice, this list of conditions and the following disclaimer.
  14  * 2. Redistributions in binary form must reproduce the above copyright
  15  *    notice, this list of conditions and the following disclaimer in the
  16  *    documentation and/or other materials provided with the distribution.
  17  * 3. Neither the name of the University nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #include <sys/types.h>
  35 #include <sys/stat.h>
  36 
  37 #include <assert.h>
  38 #include <ctype.h>
  39 #include <errno.h>
  40 #include <fcntl.h>
  41 #ifdef _WIN32
  42 #include <io.h>
  43 #endif
  44 #include <stdio.h>
  45 #include <stdlib.h>
  46 
  47 #ifndef O_BINARY
  48 #define O_BINARY 0
  49 #endif
  50 
  51 
  52 
  53 int
  54 _zip_mkstemp(char *path)
  55 {
  56 #ifdef _WIN32
  57         int ret;
  58         ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE);
  59         if (ret == -1) {
  60                 return 0;
  61         } else {
  62                 return ret;
  63         }
  64 #else
  65         int fd;   
  66         char *start, *trv;
  67         struct stat sbuf;
  68         pid_t pid;
  69 
  70         /* To guarantee multiple calls generate unique names even if
  71            the file is not created. 676 different possibilities with 7
  72            or more X's, 26 with 6 or less. */
  73         static char xtra[2] = "aa";
  74         int xcnt = 0;
  75 
  76         pid = getpid();
  77 
  78         /* Move to end of path and count trailing X's. */
  79         for (trv = path; *trv; ++trv)
  80                 if (*trv == 'X')
  81                         xcnt++;
  82                 else
  83                         xcnt = 0;       
  84 
  85         /* Use at least one from xtra.  Use 2 if more than 6 X's. */
  86         if (*(trv - 1) == 'X')
  87                 *--trv = xtra[0];
  88         if (xcnt > 6 && *(trv - 1) == 'X')
  89                 *--trv = xtra[1];
  90 
  91         /* Set remaining X's to pid digits with 0's to the left. */
  92         while (*--trv == 'X') {
  93                 *trv = (pid % 10) + '0';
  94                 pid /= 10;
  95         }
  96 
  97         /* update xtra for next call. */
  98         if (xtra[0] != 'z')
  99                 xtra[0]++;
 100         else {
 101                 xtra[0] = 'a';
 102                 if (xtra[1] != 'z')
 103                         xtra[1]++;
 104                 else
 105                         xtra[1] = 'a';
 106         }
 107 
 108         /*
 109          * check the target directory; if you have six X's and it
 110          * doesn't exist this runs for a *very* long time.
 111          */
 112         for (start = trv + 1;; --trv) {
 113                 if (trv <= path)
 114                         break;
 115                 if (*trv == '/') {
 116                         *trv = '\0';
 117                         if (stat(path, &sbuf))
 118                                 return (0);
 119                         if (!S_ISDIR(sbuf.st_mode)) {
 120                                 errno = ENOTDIR;
 121                                 return (0);
 122                         }
 123                         *trv = '/';
 124                         break;
 125                 }
 126         }
 127 
 128         for (;;) {
 129                 if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
 130                         return (fd);
 131                 if (errno != EEXIST)
 132                         return (0);
 133 
 134                 /* tricky little algorithm for backward compatibility */
 135                 for (trv = start;;) {
 136                         if (!*trv)
 137                                 return (0);
 138                         if (*trv == 'z')
 139                                 *trv++ = 'a';
 140                         else {
 141                                 if (isdigit((unsigned char)*trv))
 142                                         *trv = 'a';
 143                                 else
 144                                         ++*trv;
 145                                 break;
 146                         }
 147                 }
 148         }
 149         /*NOTREACHED*/
 150 #endif
 151 }

/* [<][>][^][v][top][bottom][index][help] */