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 #include "androidfw/misc.h"
20
21 #include <errno.h>
22 #include <sys/stat.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 <array>
32 #include <cstdio>
33 #include <cstring>
34
35 namespace android {
36
37 /*
38 * Get a file's type.
39 */
getFileType(const char * fileName)40 FileType getFileType(const char* fileName) {
41 struct stat sb;
42 if (stat(fileName, &sb) < 0) {
43 if (errno == ENOENT || errno == ENOTDIR)
44 return kFileTypeNonexistent;
45 else {
46 PLOG(ERROR) << "getFileType(): stat(" << fileName << ") failed";
47 return kFileTypeUnknown;
48 }
49 } else {
50 if (S_ISREG(sb.st_mode))
51 return kFileTypeRegular;
52 else if (S_ISDIR(sb.st_mode))
53 return kFileTypeDirectory;
54 else if (S_ISCHR(sb.st_mode))
55 return kFileTypeCharDev;
56 else if (S_ISBLK(sb.st_mode))
57 return kFileTypeBlockDev;
58 else if (S_ISFIFO(sb.st_mode))
59 return kFileTypeFifo;
60 #if defined(S_ISLNK)
61 else if (S_ISLNK(sb.st_mode))
62 return kFileTypeSymlink;
63 #endif
64 #if defined(S_ISSOCK)
65 else if (S_ISSOCK(sb.st_mode))
66 return kFileTypeSocket;
67 #endif
68 else
69 return kFileTypeUnknown;
70 }
71 }
72
getModDate(const struct stat & st)73 ModDate getModDate(const struct stat& st) {
74 #ifdef _WIN32
75 return st.st_mtime;
76 #elif defined(__APPLE__)
77 return st.st_mtimespec;
78 #else
79 return st.st_mtim;
80 #endif
81 }
82
getFileModDate(const char * fileName)83 ModDate getFileModDate(const char* fileName) {
84 struct stat sb;
85 if (stat(fileName, &sb) < 0) {
86 return kInvalidModDate;
87 }
88 return getModDate(sb);
89 }
90
getFileModDate(int fd)91 ModDate getFileModDate(int fd) {
92 struct stat sb;
93 if (fstat(fd, &sb) < 0) {
94 return kInvalidModDate;
95 }
96 if (sb.st_nlink <= 0) {
97 errno = ENOENT;
98 return kInvalidModDate;
99 }
100 return getModDate(sb);
101 }
102
103 #ifndef __linux__
104 // No need to implement these on the host, the functions only matter on a device.
isReadonlyFilesystem(const char *)105 bool isReadonlyFilesystem(const char*) {
106 return false;
107 }
isReadonlyFilesystem(int)108 bool isReadonlyFilesystem(int) {
109 return false;
110 }
isKnownWritablePath(const char *)111 bool isKnownWritablePath(const char*) {
112 return false;
113 }
114 #else // __linux__
isReadonlyFilesystem(const char * path)115 bool isReadonlyFilesystem(const char* path) {
116 if (isKnownWritablePath(path)) {
117 return false;
118 }
119 struct statfs sfs;
120 if (::statfs(path, &sfs)) {
121 PLOG(ERROR) << "isReadonlyFilesystem(): statfs(" << path << ") failed";
122 return false;
123 }
124 return (sfs.f_flags & ST_RDONLY) != 0;
125 }
126
isReadonlyFilesystem(int fd)127 bool isReadonlyFilesystem(int fd) {
128 struct statfs sfs;
129 if (::fstatfs(fd, &sfs)) {
130 PLOG(ERROR) << "isReadonlyFilesystem(): fstatfs(" << fd << ") failed";
131 return false;
132 }
133 return (sfs.f_flags & ST_RDONLY) != 0;
134 }
135
isKnownWritablePath(const char * path)136 bool isKnownWritablePath(const char* path) {
137 // We know that all paths in /data/ are writable.
138 static constexpr char kRwPrefix[] = "/data/";
139 return strncmp(kRwPrefix, path, std::size(kRwPrefix) - 1) == 0;
140 }
141
142 #endif // __linux__
143
144 } // namespace android
145