file_util_android.cc revision 00d26a728db2814620f390b418a7d6325ce5aca6
1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/file_util.h" 6 7#include <fcntl.h> 8 9#include <string> 10#include <vector> 11 12#include "base/eintr_wrapper.h" 13#include "base/file_path.h" 14#include "base/string_util.h" 15 16// just lifted off bionic, no should find out why it doesn't get linked in 17 18static int _gettemp(char *, int *, int, int); 19 20extern uint32_t arc4random(); 21 22int 23mkstemps(char *path, int slen) 24{ 25 int fd; 26 27 return (_gettemp(path, &fd, 0, slen) ? fd : -1); 28} 29 30int 31mkstemp(char *path) 32{ 33 int fd; 34 35 return (_gettemp(path, &fd, 0, 0) ? fd : -1); 36} 37 38char * 39mkdtemp(char *path) 40{ 41 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); 42} 43 44char *_mktemp(char *); 45 46char * 47_mktemp(char *path) 48{ 49 return(_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL); 50} 51 52__warn_references(mktemp, 53 "warning: mktemp() possibly used unsafely; consider using mkstemp()"); 54 55char * 56mktemp(char *path) 57{ 58 return(_mktemp(path)); 59} 60 61 62static int 63_gettemp(char *path, int *doopen, int domkdir, int slen) 64{ 65 char *start, *trv, *suffp; 66 struct stat sbuf; 67 int rval; 68 pid_t pid; 69 70 if (doopen && domkdir) { 71 errno = EINVAL; 72 return(0); 73 } 74 75 for (trv = path; *trv; ++trv) 76 ; 77 trv -= slen; 78 suffp = trv; 79 --trv; 80 if (trv < path) { 81 errno = EINVAL; 82 return (0); 83 } 84 pid = getpid(); 85 while (trv >= path && *trv == 'X' && pid != 0) { 86 *trv-- = (pid % 10) + '0'; 87 pid /= 10; 88 } 89 while (trv >= path && *trv == 'X') { 90 char c; 91 92 pid = (arc4random() & 0xffff) % (26+26); 93 if (pid < 26) 94 c = pid + 'A'; 95 else 96 c = (pid - 26) + 'a'; 97 *trv-- = c; 98 } 99 start = trv + 1; 100 101 /* 102 * check the target directory; if you have six X's and it 103 * doesn't exist this runs for a *very* long time. 104 */ 105 if (doopen || domkdir) { 106 for (;; --trv) { 107 if (trv <= path) 108 break; 109 if (*trv == '/') { 110 *trv = '\0'; 111 rval = stat(path, &sbuf); 112 *trv = '/'; 113 if (rval != 0) 114 return(0); 115 if (!S_ISDIR(sbuf.st_mode)) { 116 errno = ENOTDIR; 117 return(0); 118 } 119 break; 120 } 121 } 122 } 123 124 for (;;) { 125 if (doopen) { 126 if ((*doopen = 127 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) 128 return(1); 129 if (errno != EEXIST) 130 return(0); 131 } else if (domkdir) { 132 if (mkdir(path, 0700) == 0) 133 return(1); 134 if (errno != EEXIST) 135 return(0); 136 } else if (lstat(path, &sbuf)) 137 return(errno == ENOENT ? 1 : 0); 138 139 /* tricky little algorithm for backward compatibility */ 140 for (trv = start;;) { 141 if (!*trv) 142 return (0); 143 if (*trv == 'Z') { 144 if (trv == suffp) 145 return (0); 146 *trv++ = 'a'; 147 } else { 148 if (isdigit(*trv)) 149 *trv = 'a'; 150 else if (*trv == 'z') /* inc from z to A */ 151 *trv = 'A'; 152 else { 153 if (trv == suffp) 154 return (0); 155 ++*trv; 156 } 157 break; 158 } 159 } 160 } 161 /*NOTREACHED*/ 162} 163