• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "misc"
18 
19 //
20 // Miscellaneous utility functions.
21 //
22 #include <utils/misc.h>
23 #include <utils/Log.h>
24 
25 #include <sys/stat.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <assert.h>
29 #include <stdio.h>
30 
31 #if defined(HAVE_PTHREADS)
32 # include <pthread.h>
33 #endif
34 
35 #include <utils/Vector.h>
36 
37 using namespace android;
38 
39 namespace android {
40 
41 /*
42  * Like strdup(), but uses C++ "new" operator instead of malloc.
43  */
strdupNew(const char * str)44 char* strdupNew(const char* str)
45 {
46     char* newStr;
47     int len;
48 
49     if (str == NULL)
50         return NULL;
51 
52     len = strlen(str);
53     newStr = new char[len+1];
54     memcpy(newStr, str, len+1);
55 
56     return newStr;
57 }
58 
59 /*
60  * Concatenate an argument vector.
61  */
concatArgv(int argc,const char * const argv[])62 char* concatArgv(int argc, const char* const argv[])
63 {
64     char* newStr = NULL;
65     int len, totalLen, posn, idx;
66 
67     /*
68      * First, figure out the total length.
69      */
70     totalLen = idx = 0;
71     while (1) {
72         if (idx == argc || argv[idx] == NULL)
73             break;
74         if (idx)
75             totalLen++;  // leave a space between args
76         totalLen += strlen(argv[idx]);
77         idx++;
78     }
79 
80     /*
81      * Alloc the string.
82      */
83     newStr = new char[totalLen +1];
84     if (newStr == NULL)
85         return NULL;
86 
87     /*
88      * Finally, allocate the string and copy data over.
89      */
90     idx = posn = 0;
91     while (1) {
92         if (idx == argc || argv[idx] == NULL)
93             break;
94         if (idx)
95             newStr[posn++] = ' ';
96 
97         len = strlen(argv[idx]);
98         memcpy(&newStr[posn], argv[idx], len);
99         posn += len;
100 
101         idx++;
102     }
103 
104     assert(posn == totalLen);
105     newStr[posn] = '\0';
106 
107     return newStr;
108 }
109 
110 /*
111  * Count the #of args in an argument vector.  Don't count the final NULL.
112  */
countArgv(const char * const argv[])113 int countArgv(const char* const argv[])
114 {
115     int count = 0;
116 
117     while (argv[count] != NULL)
118         count++;
119 
120     return count;
121 }
122 
123 
124 #include <stdio.h>
125 /*
126  * Get a file's type.
127  */
getFileType(const char * fileName)128 FileType getFileType(const char* fileName)
129 {
130     struct stat sb;
131 
132     if (stat(fileName, &sb) < 0) {
133         if (errno == ENOENT || errno == ENOTDIR)
134             return kFileTypeNonexistent;
135         else {
136             fprintf(stderr, "getFileType got errno=%d on '%s'\n",
137                 errno, fileName);
138             return kFileTypeUnknown;
139         }
140     } else {
141         if (S_ISREG(sb.st_mode))
142             return kFileTypeRegular;
143         else if (S_ISDIR(sb.st_mode))
144             return kFileTypeDirectory;
145         else if (S_ISCHR(sb.st_mode))
146             return kFileTypeCharDev;
147         else if (S_ISBLK(sb.st_mode))
148             return kFileTypeBlockDev;
149         else if (S_ISFIFO(sb.st_mode))
150             return kFileTypeFifo;
151 #ifdef HAVE_SYMLINKS
152         else if (S_ISLNK(sb.st_mode))
153             return kFileTypeSymlink;
154         else if (S_ISSOCK(sb.st_mode))
155             return kFileTypeSocket;
156 #endif
157         else
158             return kFileTypeUnknown;
159     }
160 }
161 
162 /*
163  * Get a file's modification date.
164  */
getFileModDate(const char * fileName)165 time_t getFileModDate(const char* fileName)
166 {
167     struct stat sb;
168 
169     if (stat(fileName, &sb) < 0)
170         return (time_t) -1;
171 
172     return sb.st_mtime;
173 }
174 
175 /*
176  * Round up to the next highest power of 2.
177  *
178  * Found on http://graphics.stanford.edu/~seander/bithacks.html.
179  */
roundUpPower2(unsigned int val)180 unsigned int roundUpPower2(unsigned int val)
181 {
182     val--;
183     val |= val >> 1;
184     val |= val >> 2;
185     val |= val >> 4;
186     val |= val >> 8;
187     val |= val >> 16;
188     val++;
189 
190     return val;
191 }
192 
193 struct sysprop_change_callback_info {
194     sysprop_change_callback callback;
195     int priority;
196 };
197 
198 #if defined(HAVE_PTHREADS)
199 static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER;
200 static Vector<sysprop_change_callback_info>* gSyspropList = NULL;
201 #endif
202 
add_sysprop_change_callback(sysprop_change_callback cb,int priority)203 void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
204 #if defined(HAVE_PTHREADS)
205     pthread_mutex_lock(&gSyspropMutex);
206     if (gSyspropList == NULL) {
207         gSyspropList = new Vector<sysprop_change_callback_info>();
208     }
209     sysprop_change_callback_info info;
210     info.callback = cb;
211     info.priority = priority;
212     bool added = false;
213     for (size_t i=0; i<gSyspropList->size(); i++) {
214         if (priority >= gSyspropList->itemAt(i).priority) {
215             gSyspropList->insertAt(info, i);
216             added = true;
217             break;
218         }
219     }
220     if (!added) {
221         gSyspropList->add(info);
222     }
223     pthread_mutex_unlock(&gSyspropMutex);
224 #endif
225 }
226 
report_sysprop_change()227 void report_sysprop_change() {
228 #if defined(HAVE_PTHREADS)
229     pthread_mutex_lock(&gSyspropMutex);
230     Vector<sysprop_change_callback_info> listeners;
231     if (gSyspropList != NULL) {
232         listeners = *gSyspropList;
233     }
234     pthread_mutex_unlock(&gSyspropMutex);
235 
236     //ALOGI("Reporting sysprop change to %d listeners", listeners.size());
237     for (size_t i=0; i<listeners.size(); i++) {
238         listeners[i].callback();
239     }
240 #endif
241 }
242 
243 }; // namespace android
244