auto import from //depot/cupcake/@135843
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
new file mode 100644
index 0000000..5db5545
--- /dev/null
+++ b/cmds/installd/utils.c
@@ -0,0 +1,149 @@
+/*
+** Copyright 2008, 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 "installd.h"
+
+int create_pkg_path(char path[PKG_PATH_MAX],
+ const char *prefix,
+ const char *pkgname,
+ const char *postfix)
+{
+ int len;
+ const char *x;
+
+ len = strlen(pkgname);
+ if (len > PKG_NAME_MAX) {
+ return -1;
+ }
+ if ((len + strlen(prefix) + strlen(postfix)) >= PKG_PATH_MAX) {
+ return -1;
+ }
+
+ x = pkgname;
+ while (*x) {
+ if (isalnum(*x) || (*x == '_')) {
+ /* alphanumeric or underscore are fine */
+ } else if (*x == '.') {
+ if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
+ /* periods must not be first, last, or doubled */
+ LOGE("invalid package name '%s'\n", pkgname);
+ return -1;
+ }
+ } else {
+ /* anything not A-Z, a-z, 0-9, _, or . is invalid */
+ LOGE("invalid package name '%s'\n", pkgname);
+ return -1;
+ }
+ x++;
+ }
+
+ sprintf(path, "%s%s%s", prefix, pkgname, postfix);
+ return 0;
+}
+
+static int _delete_dir_contents(DIR *d, const char *ignore)
+{
+ int result = 0;
+ struct dirent *de;
+ int dfd;
+
+ dfd = dirfd(d);
+
+ if (dfd < 0) return -1;
+
+ while ((de = readdir(d))) {
+ const char *name = de->d_name;
+
+ /* skip the ignore name if provided */
+ if (ignore && !strcmp(name, ignore)) continue;
+
+ if (de->d_type == DT_DIR) {
+ int r, subfd;
+ DIR *subdir;
+
+ /* always skip "." and ".." */
+ if (name[0] == '.') {
+ if (name[1] == 0) continue;
+ if ((name[1] == '.') && (name[2] == 0)) continue;
+ }
+
+ subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (subfd < 0) {
+ result = -1;
+ continue;
+ }
+ subdir = fdopendir(subfd);
+ if (subdir == NULL) {
+ close(subfd);
+ result = -1;
+ continue;
+ }
+ if (_delete_dir_contents(subdir, 0)) {
+ result = -1;
+ }
+ closedir(subdir);
+ if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
+ result = -1;
+ }
+ } else {
+ if (unlinkat(dfd, name, 0) < 0) {
+ result = -1;
+ }
+ }
+ }
+
+ return result;
+}
+
+int delete_dir_contents(const char *pathname,
+ int also_delete_dir,
+ const char *ignore)
+{
+ int res = 0;
+ DIR *d;
+
+ d = opendir(pathname);
+ if (d == NULL) {
+ return -errno;
+ }
+ res = _delete_dir_contents(d, ignore);
+ closedir(d);
+ if (also_delete_dir) {
+ if (rmdir(pathname)) {
+ res = -1;
+ }
+ }
+ return res;
+}
+
+int delete_dir_contents_fd(int dfd, const char *name)
+{
+ int fd, res;
+ DIR *d;
+
+ fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+ if (fd < 0) {
+ return -1;
+ }
+ d = fdopendir(fd);
+ if (d == NULL) {
+ close(fd);
+ return -1;
+ }
+ res = _delete_dir_contents(d, 0);
+ closedir(d);
+ return res;
+}