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 <androidfw/misc.h>
23 
24 #include "android-base/logging.h"
25 
26 #ifdef __linux__
27 #include <sys/statvfs.h>
28 #include <sys/vfs.h>
29 #endif  // __linux__
30 
31 #include <cstring>
32 #include <cstdio>
33 #include <errno.h>
34 #include <sys/stat.h>
35 
36 namespace android {
37 
38 /*
39  * Get a file's type.
40  */
getFileType(const char * fileName)41 FileType getFileType(const char* fileName)
42 {
43     struct stat sb;
44 
45     if (stat(fileName, &sb) < 0) {
46         if (errno == ENOENT || errno == ENOTDIR)
47             return kFileTypeNonexistent;
48         else {
49             PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
50             return kFileTypeUnknown;
51         }
52     } else {
53         if (S_ISREG(sb.st_mode))
54             return kFileTypeRegular;
55         else if (S_ISDIR(sb.st_mode))
56             return kFileTypeDirectory;
57         else if (S_ISCHR(sb.st_mode))
58             return kFileTypeCharDev;
59         else if (S_ISBLK(sb.st_mode))
60             return kFileTypeBlockDev;
61         else if (S_ISFIFO(sb.st_mode))
62             return kFileTypeFifo;
63 #if defined(S_ISLNK)
64         else if (S_ISLNK(sb.st_mode))
65             return kFileTypeSymlink;
66 #endif
67 #if defined(S_ISSOCK)
68         else if (S_ISSOCK(sb.st_mode))
69             return kFileTypeSocket;
70 #endif
71         else
72             return kFileTypeUnknown;
73     }
74 }
75 
76 /*
77  * Get a file's modification date.
78  */
getFileModDate(const char * fileName)79 time_t getFileModDate(const char* fileName) {
80     struct stat sb;
81     if (stat(fileName, &sb) < 0) {
82         return (time_t)-1;
83     }
84     return sb.st_mtime;
85 }
86 
getFileModDate(int fd)87 time_t getFileModDate(int fd) {
88     struct stat sb;
89     if (fstat(fd, &sb) < 0) {
90         return (time_t)-1;
91     }
92     if (sb.st_nlink <= 0) {
93         errno = ENOENT;
94         return (time_t)-1;
95     }
96     return sb.st_mtime;
97 }
98 
99 #ifndef __linux__
100 // No need to implement these on the host, the functions only matter on a device.
isReadonlyFilesystem(const char *)101 bool isReadonlyFilesystem(const char*) {
102     return false;
103 }
isReadonlyFilesystem(int)104 bool isReadonlyFilesystem(int) {
105     return false;
106 }
107 #else   // __linux__
isReadonlyFilesystem(const char * path)108 bool isReadonlyFilesystem(const char* path) {
109     struct statfs sfs;
110     if (::statfs(path, &sfs)) {
111         PLOG(ERROR) << "isReadonlyFilesystem(): statfs(" << path << ") failed";
112         return false;
113     }
114     return (sfs.f_flags & ST_RDONLY) != 0;
115 }
116 
isReadonlyFilesystem(int fd)117 bool isReadonlyFilesystem(int fd) {
118     struct statfs sfs;
119     if (::fstatfs(fd, &sfs)) {
120         PLOG(ERROR) << "isReadonlyFilesystem(): fstatfs(" << fd << ") failed";
121         return false;
122     }
123     return (sfs.f_flags & ST_RDONLY) != 0;
124 }
125 #endif  // __linux__
126 
127 }; // namespace android
128