• 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 #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