Loading include/cutils/fs.h 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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 */ include/cutils/multiuser.h +3 −3 Original line number Diff line number Diff line Loading @@ -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 } Loading libcutils/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ ifeq ($(WINDOWS_HOST_ONLY),1) else commonSources += \ abort_socket.c \ fs.c \ selector.c \ tztime.c \ multiuser.c \ Loading libcutils/fs.c 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * 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; } libcutils/multiuser.c +3 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading
include/cutils/fs.h 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * 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 */
include/cutils/multiuser.h +3 −3 Original line number Diff line number Diff line Loading @@ -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 } Loading
libcutils/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ ifeq ($(WINDOWS_HOST_ONLY),1) else commonSources += \ abort_socket.c \ fs.c \ selector.c \ tztime.c \ multiuser.c \ Loading
libcutils/fs.c 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * 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; }
libcutils/multiuser.c +3 −3 Original line number Diff line number Diff line Loading @@ -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); }