blob: 052d9e8dbe6805dcc2278194cd46066703ffce95 [file] [log] [blame]
Adam Lesinski16c4d152014-01-24 13:27:13 -08001/*
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
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080019#include "androidfw/misc.h"
20
21#include <errno.h>
22#include <sys/stat.h>
Adam Lesinski16c4d152014-01-24 13:27:13 -080023
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -080024#include "android-base/logging.h"
Adam Lesinski16c4d152014-01-24 13:27:13 -080025
Yurii Zubrytskyi98e12d02022-12-01 09:34:02 -080026#ifdef __linux__
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -080027#include <sys/statvfs.h>
28#include <sys/vfs.h>
Yurii Zubrytskyi98e12d02022-12-01 09:34:02 -080029#endif // __linux__
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -080030
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080031#include <array>
Yurii Zubrytskyi5f0df422024-12-16 18:12:02 -080032#include <cstdio>
33#include <cstring>
Yurii Zubrytskyi5f0df422024-12-16 18:12:02 -080034
Adam Lesinski16c4d152014-01-24 13:27:13 -080035namespace android {
36
37/*
38 * Get a file's type.
39 */
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080040FileType 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;
Elliott Hughes1bf24812015-01-12 14:33:04 -080060#if defined(S_ISLNK)
Adam Lesinski16c4d152014-01-24 13:27:13 -080061 else if (S_ISLNK(sb.st_mode))
62 return kFileTypeSymlink;
Elliott Hughes1bf24812015-01-12 14:33:04 -080063#endif
64#if defined(S_ISSOCK)
Adam Lesinski16c4d152014-01-24 13:27:13 -080065 else if (S_ISSOCK(sb.st_mode))
66 return kFileTypeSocket;
67#endif
68 else
69 return kFileTypeUnknown;
70 }
71}
72
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -080073ModDate getModDate(const struct stat& st) {
Yurii Zubrytskyi5f0df422024-12-16 18:12:02 -080074#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
Yurii Zubrytskyie7c1f002024-01-30 13:50:57 -080081}
Adam Lesinski16c4d152014-01-24 13:27:13 -080082
Yurii Zubrytskyi5f0df422024-12-16 18:12:02 -080083ModDate getFileModDate(const char* fileName) {
84 struct stat sb;
85 if (stat(fileName, &sb) < 0) {
86 return kInvalidModDate;
87 }
88 return getModDate(sb);
89}
90
91ModDate 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);
Adam Lesinski16c4d152014-01-24 13:27:13 -0800101}
102
Yurii Zubrytskyi98e12d02022-12-01 09:34:02 -0800103#ifndef __linux__
104// No need to implement these on the host, the functions only matter on a device.
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -0800105bool isReadonlyFilesystem(const char*) {
106 return false;
107}
108bool isReadonlyFilesystem(int) {
109 return false;
110}
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -0800111bool isKnownWritablePath(const char*) {
112 return false;
113}
Yurii Zubrytskyi98e12d02022-12-01 09:34:02 -0800114#else // __linux__
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -0800115bool isReadonlyFilesystem(const char* path) {
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -0800116 if (isKnownWritablePath(path)) {
117 return false;
118 }
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -0800119 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
127bool 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}
Yurii Zubrytskyi548c1ab2025-02-06 15:41:54 -0800135
136bool 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
Yurii Zubrytskyi98e12d02022-12-01 09:34:02 -0800142#endif // __linux__
Yurii Zubrytskyi2ab44472022-11-30 00:56:22 -0800143
Yurii Zubrytskyi5f0df422024-12-16 18:12:02 -0800144} // namespace android