Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: base/os_compat_android.cc

Issue 10696114: Upstreaming diffs in os_compat_android.cc (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/os_compat_android.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/os_compat_android.h" 5 #include "base/os_compat_android.h"
6 6
7 #include <errno.h>
8 #include <math.h>
9 #include <sys/stat.h>
7 #include <time64.h> 10 #include <time64.h>
8 11
9 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
10 13
11 // There is no futimes() avaiable in Bionic, so we provide our own 14 // There is no futimes() avaiable in Bionic, so we provide our own
12 // implementation until it is there. 15 // implementation until it is there.
13 extern "C" { 16 extern "C" {
14 17
15 int futimes(int fd, const struct timeval tv[2]) { 18 int futimes(int fd, const struct timeval tv[2]) {
16 const std::string fd_path = StringPrintf("/proc/self/fd/%d", fd); 19 const std::string fd_path = StringPrintf("/proc/self/fd/%d", fd);
17 return utimes(fd_path.c_str(), tv); 20 return utimes(fd_path.c_str(), tv);
18 } 21 }
19 22
20 // Android has only timegm64() and no timegm(). 23 // Android has only timegm64() and no timegm().
21 // We replicate the behaviour of timegm() when the result overflows time_t. 24 // We replicate the behaviour of timegm() when the result overflows time_t.
22 time_t timegm(struct tm* const t) { 25 time_t timegm(struct tm* const t) {
23 // time_t is signed on Android. 26 // time_t is signed on Android.
24 static const time_t kTimeMax = ~(1 << (sizeof(time_t) * CHAR_BIT - 1)); 27 static const time_t kTimeMax = ~(1 << (sizeof(time_t) * CHAR_BIT - 1));
25 static const time_t kTimeMin = (1 << (sizeof(time_t) * CHAR_BIT - 1)); 28 static const time_t kTimeMin = (1 << (sizeof(time_t) * CHAR_BIT - 1));
26 time64_t result = timegm64(t); 29 time64_t result = timegm64(t);
27 if (result < kTimeMin || result > kTimeMax) 30 if (result < kTimeMin || result > kTimeMax)
28 return -1; 31 return -1;
29 return result; 32 return result;
30 } 33 }
31 34
35 // The following is only needed when building with GCC 4.6 or higher
36 // (i.e. not with Android GCC 4.4.3, nor with Clang).
37 //
38 // GCC is now capable of optimizing successive calls to sin() and cos() into
39 // a single call to sincos(). This means that source code that looks like:
40 //
41 // double c, s;
42 // c = cos(angle);
43 // s = sin(angle);
44 //
45 // Will generate machine code that looks like:
46 //
47 // double c, s;
48 // sincos(angle, &s, &c);
49 //
50 // Unfortunately, sincos() and friends are not part of the Android libm.so
51 // library provided by the NDK for API level 9. When the optimization kicks
52 // in, it makes the final build fail with a puzzling message (puzzling
53 // because 'sincos' doesn't appear anywhere in the sources!).
54 //
55 // To solve this, we provide our own implementation of the sincos() function
56 // and related friends. Note that we must also explicitely tell GCC to disable
57 // optimizations when generating these. Otherwise, the generated machine code
58 // for each function would simply end up calling itself, resulting in a
59 // runtime crash due to stack overflow.
60 //
61 #if defined(__GNUC__) && !defined(__clang__)
62
63 // For the record, Clang does not support the 'optimize' attribute.
64 // In the unlikely event that it begins performing this optimization too,
65 // we'll have to find a different way to achieve this. NOTE: Tested with O1
66 // which still performs the optimization.
67 //
68 #define GCC_NO_OPTIMIZE __attribute__((optimize("O0")))
69
70 GCC_NO_OPTIMIZE
71 void sincos(double angle, double* s, double *c)
72 {
brettw 2012/07/10 20:56:04 Style: Check placement of { throughout this patch
felipeg 2012/07/11 15:26:24 Done.
73 *c = cos(angle);
74 *s = sin(angle);
75 }
76
77 GCC_NO_OPTIMIZE
78 void sincosf(float angle, float* s, float* c)
79 {
80 *c = cosf(angle);
81 *s = sinf(angle);
82 }
83
84 #endif // __GNUC__ && !__clang__
85
86 // An implementation of mkdtemp, since it is not exposed by the NDK
87 // for native API level 9 that we target.
88 char* mkdtemp(char* path)
89 {
90 if (path == NULL) {
91 errno = EINVAL;
92 return NULL;
93 }
94
95 int len = strlen(path);
96 int suffix = len;
97
98 // The last six characters of 'path' must be XXXXXX, but the string
99 // can be terminated by a longer string of 'X'. Find its start at
100 // 'suffix'.
101 while (suffix > 0 && path[suffix-1] == 'X')
102 suffix--;
103
104 // Error if there aren't at least 6 'X' characters at the end
105 if (len - suffix < 6) {
106 errno = EINVAL;
107 return NULL;
108 }
109
110 // If the path contains a directory, as in /tmp/foo/XXXXXXXX, make sure
111 // that /tmp/foo exists, otherwise we're going to loop a really long
112 // time for nothing below
113 char* dirsep = strrchr(path, '/');
114 if (dirsep != NULL) {
115 struct stat st;
116 int ret;
117
118 *dirsep = '\0'; // Terminating directory path temporarily
brettw 2012/07/10 20:56:04 Style: two spaces before end-of-line comments. Che
felipeg 2012/07/11 15:26:24 Done.
119
120 ret = stat(path, &st);
121
122 *dirsep = '/'; // Restoring directory separator
123 if (ret < 0) { // Directory probably does not exist
124 return NULL;
125 }
brettw 2012/07/10 20:56:04 Don't use {} here since you don't elsewhere.
felipeg 2012/07/11 15:26:24 Done.
126 if (!S_ISDIR(st.st_mode)) { // Not a directory
127 errno = ENOTDIR;
128 return NULL;
129 }
130 }
131
132 // Now replace all the XXXXXs with a random alphanumerical string. We're
133 // going to use something like <randomchars><pid>, where <randomchars> is
134 // a string of random alphabetical characters, and <pid> is the decimal
135 // pid string. This matches the BSD implementation.
brettw 2012/07/10 20:56:04 I wonder if all of this is necessary. The man page
digit1 2012/07/11 15:40:48 First, for the record, this code is taken from rec
136 pid_t pid = gettid();
137 int pos = len - 1;
138
139 // First, write the pid from last to first digit
140 while (pos >= suffix && pid != 0) {
141 path[pos--] = '0' + (pid % 10);
142 pid /= 10;
143 }
144
145 // Then, add some random chars until we cover all the XXXXs
146 while (pos >= suffix) {
147 int ch = (arc4random() & 0xffff) % (26+26);
148 if (ch < 26)
149 ch = 'A' + ch;
150 else
151 ch = 'a' + (ch - 26);
152
153 path[pos--] = (char)ch;
brettw 2012/07/10 20:56:04 Don't use C casts, use static_cast.
felipeg 2012/07/11 15:26:24 Done.
154 }
155
156 // Now loop until we CAN create a directory by that name. Otherwise,
157 // 'increment' the characters after suffix to find a free one.
158 for (;;) {
159
160 if (mkdir(path, 0700) == 0) {
brettw 2012/07/10 20:56:04 I'd skip the blank line above here.
felipeg 2012/07/11 15:26:24 Done.
161 // We just created the directory succesfully.
162 return path;
163 }
164
165 if (errno != EEXIST) {
166 // The directory doesn't exist, but an error occured
167 return NULL;
168 }
169
170 // The directory does exist, find a new name by 'incrementing' from
171 // left to right, the rules are:
172 // A -> B
173 // B -> C
174 // ...
175 // Z -> a
176 // a -> b
177 // b -> c
178 // ...
179 // z -> A + increment the next character
180 //
181 // 0..9 -> A
182 pos = suffix;
183 for (;;) {
184 int ch = path[pos];
185 if (ch == 'Z') { // Z -> a
186 path[pos] = 'a';
187 break;
188 }
189 if (ch == 'z') { // z -> A + increment the next character
190 path[pos++] = 'A';
191 if (pos == len) {
192 // uh-oh, we're out of candidates here
193 return 0;
194 }
195 continue;
196 }
197 if (ch >= '0' && ch <= '9') { // 0...9 -> A
198 path[pos] = 'A';
199 break;
200 }
201 path[pos] += 1; // otherwise: $ch -> $ch + 1
202 break;
203 }
204 }
205 }
206
32 } // extern "C" 207 } // extern "C"
OLDNEW
« no previous file with comments | « base/os_compat_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698