summaryrefslogtreecommitdiffstats
path: root/libcutils/fs.c
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2012-08-27 15:03:37 -0700
committerJeff Sharkey <jsharkey@android.com>2012-08-30 10:29:41 -0700
commit9685194fc94510a33201aee9b80c23f206ccfe67 (patch)
tree7a58f5b42c47df2f49df7c6cb55cd0b8a30bec67 /libcutils/fs.c
parent84ac402fa1860817ed100d189b0613f8c4b0ef2a (diff)
downloadsystem_core-9685194fc94510a33201aee9b80c23f206ccfe67.zip
system_core-9685194fc94510a33201aee9b80c23f206ccfe67.tar.gz
system_core-9685194fc94510a33201aee9b80c23f206ccfe67.tar.bz2
File-system utilities for installd and zygote.
Bug: 7008879 Change-Id: Ia54b8d4ad434e8973f235e2a4728651814bef8a9
Diffstat (limited to 'libcutils/fs.c')
-rw-r--r--libcutils/fs.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/libcutils/fs.c b/libcutils/fs.c
new file mode 100644
index 0000000..1788eca
--- /dev/null
+++ b/libcutils/fs.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cutils/fs.h>
+#include <cutils/log.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+
+#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+#define BUF_SIZE 64
+
+int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid) {
+ // Check if path needs to be created
+ struct stat sb;
+ if (lstat(path, &sb) == -1) {
+ if (errno == ENOENT) {
+ goto create;
+ } else {
+ ALOGE("Failed to stat(%s): %s", path, strerror(errno));
+ return -1;
+ }
+ }
+
+ // Exists, verify status
+ if (!S_ISDIR(sb.st_mode)) {
+ ALOGE("Not a directory: %s", path);
+ return -1;
+ }
+ if (((sb.st_mode & ALL_PERMS) == mode) && (sb.st_uid == uid) && (sb.st_gid == gid)) {
+ return 0;
+ } else {
+ goto fixup;
+ }
+
+create:
+ if (mkdir(path, mode) == -1) {
+ ALOGE("Failed to mkdir(%s): %s", path, strerror(errno));
+ return -1;
+ }
+
+fixup:
+ if (chmod(path, mode) == -1) {
+ ALOGE("Failed to chown(%s, %d): %s", path, mode, strerror(errno));
+ return -1;
+ }
+ if (chown(path, uid, gid) == -1) {
+ ALOGE("Failed to chown(%s, %d, %d): %s", path, uid, gid, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+int fs_read_atomic_int(const char* path, int* out_value) {
+ int fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ ALOGE("Failed to read %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ char buf[BUF_SIZE];
+ if (read(fd, buf, BUF_SIZE) == -1) {
+ ALOGE("Failed to read %s: %s", path, strerror(errno));
+ goto fail;
+ }
+ if (sscanf(buf, "%d", out_value) != 1) {
+ ALOGE("Failed to parse %s: %s", path, strerror(errno));
+ goto fail;
+ }
+ close(fd);
+ return 0;
+
+fail:
+ close(fd);
+ *out_value = -1;
+ return -1;
+}
+
+int fs_write_atomic_int(const char* path, int value) {
+ char temp[PATH_MAX];
+ if (snprintf(temp, PATH_MAX, "%s.XXXXXX", path) >= PATH_MAX) {
+ ALOGE("Path too long");
+ return -1;
+ }
+
+ int fd = mkstemp(temp);
+ if (fd == -1) {
+ ALOGE("Failed to open %s: %s", temp, strerror(errno));
+ return -1;
+ }
+
+ char buf[BUF_SIZE];
+ int len = snprintf(buf, BUF_SIZE, "%d", value) + 1;
+ if (len > BUF_SIZE) {
+ ALOGE("Value %d too large: %s", value, strerror(errno));
+ goto fail;
+ }
+ if (write(fd, buf, len) < len) {
+ ALOGE("Failed to write %s: %s", temp, strerror(errno));
+ goto fail;
+ }
+ if (close(fd) == -1) {
+ ALOGE("Failed to close %s: %s", temp, strerror(errno));
+ goto fail_closed;
+ }
+
+ if (rename(temp, path) == -1) {
+ ALOGE("Failed to rename %s to %s: %s", temp, path, strerror(errno));
+ goto fail_closed;
+ }
+
+ return 0;
+
+fail:
+ close(fd);
+fail_closed:
+ unlink(temp);
+ return -1;
+}