diff options
-rw-r--r-- | include/cutils/fs.h | 47 | ||||
-rw-r--r-- | include/cutils/multiuser.h | 6 | ||||
-rw-r--r-- | libcutils/Android.mk | 1 | ||||
-rw-r--r-- | libcutils/fs.c | 138 | ||||
-rw-r--r-- | libcutils/multiuser.c | 6 |
5 files changed, 192 insertions, 6 deletions
diff --git a/include/cutils/fs.h b/include/cutils/fs.h new file mode 100644 index 0000000..04c8839 --- /dev/null +++ b/include/cutils/fs.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef __CUTILS_FS_H +#define __CUTILS_FS_H + +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Ensure that directory exists with given mode and owners. + */ +extern int fs_prepare_dir(const char* path, mode_t mode, uid_t uid, gid_t gid); + +/* + * Read single plaintext integer from given file, correctly handling files + * partially written with fs_write_atomic_int(). + */ +extern int fs_read_atomic_int(const char* path, int* value); + +/* + * Write single plaintext integer to given file, creating backup while + * in progress. + */ +extern int fs_write_atomic_int(const char* path, int value); + +#ifdef __cplusplus +} +#endif + +#endif /* __CUTILS_FS_H */ diff --git a/include/cutils/multiuser.h b/include/cutils/multiuser.h index 0bf403c..635ddb1 100644 --- a/include/cutils/multiuser.h +++ b/include/cutils/multiuser.h @@ -30,9 +30,9 @@ extern "C" { typedef uid_t userid_t; typedef uid_t appid_t; -extern userid_t multiuser_getUserId(uid_t uid); -extern appid_t multiuser_getAppId(uid_t uid); -extern uid_t multiuser_getUid(userid_t userId, appid_t appId); +extern userid_t multiuser_get_user_id(uid_t uid); +extern appid_t multiuser_get_app_id(uid_t uid); +extern uid_t multiuser_get_uid(userid_t userId, appid_t appId); #ifdef __cplusplus } diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 9c48ad2..d9bd8d8 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -75,6 +75,7 @@ ifeq ($(WINDOWS_HOST_ONLY),1) else commonSources += \ abort_socket.c \ + fs.c \ selector.c \ tztime.c \ multiuser.c \ 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; +} diff --git a/libcutils/multiuser.c b/libcutils/multiuser.c index 3c86cee..7c74bb8 100644 --- a/libcutils/multiuser.c +++ b/libcutils/multiuser.c @@ -16,14 +16,14 @@ #include <cutils/multiuser.h> -userid_t multiuser_getUserId(uid_t uid) { +userid_t multiuser_get_user_id(uid_t uid) { return uid / MULTIUSER_APP_PER_USER_RANGE; } -appid_t multiuser_getAppId(uid_t uid) { +appid_t multiuser_get_app_id(uid_t uid) { return uid % MULTIUSER_APP_PER_USER_RANGE; } -uid_t multiuser_getUid(userid_t userId, appid_t appId) { +uid_t multiuser_get_uid(userid_t userId, appid_t appId) { return userId * MULTIUSER_APP_PER_USER_RANGE + (appId % MULTIUSER_APP_PER_USER_RANGE); } |