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 int
  53 _zip_mkstemp(char *path)
  54 {
  55 #ifdef _WIN32
  56         int ret;
  57         ret = _creat(_mktemp(path), _S_IREAD|_S_IWRITE);
  58         if (ret == -1) {
  59                 return 0;
  60         } else {
  61                 return ret;
  62         }
  63 #else
  64         int fd;   
  65         char *start, *trv;
  66         struct stat sbuf;
  67         pid_t pid;
  68 
  69         /* To guarantee multiple calls generate unique names even if
  70            the file is not created. 676 different possibilities with 7
  71            or more X's, 26 with 6 or less. */
  72         static char xtra[2] = "aa";
  73         int xcnt = 0;
  74 
  75         pid = getpid();
  76 
  77         /* Move to end of path and count trailing X's. */
  78         for (trv = path; *trv; ++trv)
  79                 if (*trv == 'X')
  80                         xcnt++;
  81                 else
  82                         xcnt = 0;       
  83 
  84         /* Use at least one from xtra.  Use 2 if more than 6 X's. */
  85         if (*(trv - 1) == 'X')
  86                 *--trv = xtra[0];
  87         if (xcnt > 6 && *(trv - 1) == 'X')
  88                 *--trv = xtra[1];
  89 
  90         /* Set remaining X's to pid digits with 0's to the left. */
  91         while (*--trv == 'X') {
  92                 *trv = (pid % 10) + '0';
  93                 pid /= 10;
  94         }
  95 
  96         /* update xtra for next call. */
  97         if (xtra[0] != 'z')
  98                 xtra[0]++;
  99         else {
 100                 xtra[0] = 'a';
 101                 if (xtra[1] != 'z')
 102                         xtra[1]++;
 103                 else
 104                         xtra[1] = 'a';
 105         }
 106 
 107         /*
 108          * check the target directory; if you have six X's and it
 109          * doesn't exist this runs for a *very* long time.
 110          */
 111         for (start = trv + 1;; --trv) {
 112                 if (trv <= path)
 113                         break;
 114                 if (*trv == '/') {
 115                         *trv = '\0';
 116                         if (stat(path, &sbuf))
 117                                 return (0);
 118                         if (!S_ISDIR(sbuf.st_mode)) {
 119                                 errno = ENOTDIR;
 120                                 return (0);
 121                         }
 122                         *trv = '/';
 123                         break;
 124                 }
 125         }
 126 
 127         for (;;) {
 128                 if ((fd=open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
 129                         return (fd);
 130                 if (errno != EEXIST)
 131                         return (0);
 132 
 133                 /* tricky little algorithm for backward compatibility */
 134                 for (trv = start;;) {
 135                         if (!*trv)
 136                                 return (0);
 137                         if (*trv == 'z')
 138                                 *trv++ = 'a';
 139                         else {
 140                                 if (isdigit((unsigned char)*trv))
 141                                         *trv = 'a';
 142                                 else
 143                                         ++*trv;
 144                                 break;
 145                         }
 146                 }
 147         }
 148         /*NOTREACHED*/
 149 #endif
 150 }

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