misc.cpp revision 53095e25d69206bea1ac15a7382ab8b61155c0c1
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
37using namespace android;
38
39namespace android {
40
41/*
42 * Get a file's type.
43 */
44FileType 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 */
81time_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
91struct sysprop_change_callback_info {
92    sysprop_change_callback callback;
93    int priority;
94};
95
96#if defined(HAVE_PTHREADS)
97static pthread_mutex_t gSyspropMutex = PTHREAD_MUTEX_INITIALIZER;
98static Vector<sysprop_change_callback_info>* gSyspropList = NULL;
99#endif
100
101void 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
125void 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