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 * Get a file's type. 43 */ 44 FileType getFileType(const char* fileName) 45 { 46 struct stat sb; 47 48 if (stat(fileName, &sb) < 0) { 49 if (errno == ENOENT || errno == ENOTDIR) 50 return kFileTypeNonexistent; 51 else { 52 fprintf(stderr, "getFileType got errno=%d on '%s'\n", 53 errno, fileName); 54 return kFileTypeUnknown; 55 } 56 } else { 57 if (S_ISREG(sb.st_mode)) 58 return kFileTypeRegular; 59 else if (S_ISDIR(sb.st_mode)) 60 return kFileTypeDirectory; 61 else if (S_ISCHR(sb.st_mode)) 62 return kFileTypeCharDev; 63 else if (S_ISBLK(sb.st_mode)) 64 return kFileTypeBlockDev; 65 else if (S_ISFIFO(sb.st_mode)) 66 return kFileTypeFifo; 67 #ifdef HAVE_SYMLINKS 68 else if (S_ISLNK(sb.st_mode)) 69 return kFileTypeSymlink; 70 else if (S_ISSOCK(sb.st_mode)) 71 return kFileTypeSocket; 72 #endif 73 else 74 return kFileTypeUnknown; 75 } 76 } 77 78 /* 79 * Get a file's modification date. 80 */ 81 time_t getFileModDate(const char* fileName) 82 { 83 struct stat sb; 84 85 if (stat(fileName, &sb) < 0) 86 return (time_t) -1; 87 88 return sb.st_mtime; 89 } 90 91 struct sysprop_change_callback_info { 92 sysprop_change_callback callback; 93 int priority; 94 }; 95 96 #if defined(HAVE_PTHREADS) 97 static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER; 98 static Vector<sysprop_change_callback_info>* gSyspropList = NULL; 99 #endif 100 101 void add_sysprop_change_callback(sysprop_change_callback cb, int priority) { 102 #if defined(HAVE_PTHREADS) 103 pthread_mutex_lock(&gSyspropMutex); 104 if (gSyspropList == NULL) { 105 gSyspropList = new Vector<sysprop_change_callback_info>(); 106 } 107 sysprop_change_callback_info info; 108 info.callback = cb; 109 info.priority = priority; 110 bool added = false; 111 for (size_t i=0; i<gSyspropList->size(); i++) { 112 if (priority >= gSyspropList->itemAt(i).priority) { 113 gSyspropList->insertAt(info, i); 114 added = true; 115 break; 116 } 117 } 118 if (!added) { 119 gSyspropList->add(info); 120 } 121 pthread_mutex_unlock(&gSyspropMutex); 122 #endif 123 } 124 125 void report_sysprop_change() { 126 #if defined(HAVE_PTHREADS) 127 pthread_mutex_lock(&gSyspropMutex); 128 Vector<sysprop_change_callback_info> listeners; 129 if (gSyspropList != NULL) { 130 listeners = *gSyspropList; 131 } 132 pthread_mutex_unlock(&gSyspropMutex); 133 134 //ALOGI("Reporting sysprop change to %d listeners", listeners.size()); 135 for (size_t i=0; i<listeners.size(); i++) { 136 listeners[i].callback(); 137 } 138 #endif 139 } 140 141 }; // namespace android 142