utils.c revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1/* 2** Copyright 2008, 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#include "installd.h" 18 19int create_pkg_path(char path[PKG_PATH_MAX], 20 const char *prefix, 21 const char *pkgname, 22 const char *postfix) 23{ 24 int len; 25 const char *x; 26 27 len = strlen(pkgname); 28 if (len > PKG_NAME_MAX) { 29 return -1; 30 } 31 if ((len + strlen(prefix) + strlen(postfix)) >= PKG_PATH_MAX) { 32 return -1; 33 } 34 35 x = pkgname; 36 while (*x) { 37 if (isalnum(*x) || (*x == '_')) { 38 /* alphanumeric or underscore are fine */ 39 } else if (*x == '.') { 40 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 41 /* periods must not be first, last, or doubled */ 42 LOGE("invalid package name '%s'\n", pkgname); 43 return -1; 44 } 45 } else { 46 /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 47 LOGE("invalid package name '%s'\n", pkgname); 48 return -1; 49 } 50 x++; 51 } 52 53 sprintf(path, "%s%s%s", prefix, pkgname, postfix); 54 return 0; 55} 56 57static int _delete_dir_contents(DIR *d, const char *ignore) 58{ 59 int result = 0; 60 struct dirent *de; 61 int dfd; 62 63 dfd = dirfd(d); 64 65 if (dfd < 0) return -1; 66 67 while ((de = readdir(d))) { 68 const char *name = de->d_name; 69 70 /* skip the ignore name if provided */ 71 if (ignore && !strcmp(name, ignore)) continue; 72 73 if (de->d_type == DT_DIR) { 74 int r, subfd; 75 DIR *subdir; 76 77 /* always skip "." and ".." */ 78 if (name[0] == '.') { 79 if (name[1] == 0) continue; 80 if ((name[1] == '.') && (name[2] == 0)) continue; 81 } 82 83 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 84 if (subfd < 0) { 85 result = -1; 86 continue; 87 } 88 subdir = fdopendir(subfd); 89 if (subdir == NULL) { 90 close(subfd); 91 result = -1; 92 continue; 93 } 94 if (_delete_dir_contents(subdir, 0)) { 95 result = -1; 96 } 97 closedir(subdir); 98 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 99 result = -1; 100 } 101 } else { 102 if (unlinkat(dfd, name, 0) < 0) { 103 result = -1; 104 } 105 } 106 } 107 108 return result; 109} 110 111int delete_dir_contents(const char *pathname, 112 int also_delete_dir, 113 const char *ignore) 114{ 115 int res = 0; 116 DIR *d; 117 118 d = opendir(pathname); 119 if (d == NULL) { 120 return -errno; 121 } 122 res = _delete_dir_contents(d, ignore); 123 closedir(d); 124 if (also_delete_dir) { 125 if (rmdir(pathname)) { 126 res = -1; 127 } 128 } 129 return res; 130} 131 132int delete_dir_contents_fd(int dfd, const char *name) 133{ 134 int fd, res; 135 DIR *d; 136 137 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 138 if (fd < 0) { 139 return -1; 140 } 141 d = fdopendir(fd); 142 if (d == NULL) { 143 close(fd); 144 return -1; 145 } 146 res = _delete_dir_contents(d, 0); 147 closedir(d); 148 return res; 149} 150