utils.c revision c028be4f3b8c7476b46859f66c3f33d528adf181
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 int alpha = -1; 37 while (*x) { 38 if (isalnum(*x) || (*x == '_')) { 39 /* alphanumeric or underscore are fine */ 40 } else if (*x == '.') { 41 if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) { 42 /* periods must not be first, last, or doubled */ 43 LOGE("invalid package name '%s'\n", pkgname); 44 return -1; 45 } 46 } else if (*x == '-') { 47 /* Suffix -X is fine to let versioning of packages. 48 But whatever follows should be alphanumeric.*/ 49 alpha = 1; 50 }else { 51 /* anything not A-Z, a-z, 0-9, _, or . is invalid */ 52 LOGE("invalid package name '%s'\n", pkgname); 53 return -1; 54 } 55 x++; 56 } 57 if (alpha == 1) { 58 // Skip current character 59 x++; 60 while (*x) { 61 if (!isalnum(*x)) { 62 LOGE("invalid package name '%s' should include only numbers after -\n", pkgname); 63 return -1; 64 } 65 x++; 66 } 67 } 68 69 sprintf(path, "%s%s%s", prefix, pkgname, postfix); 70 return 0; 71} 72 73static int _delete_dir_contents(DIR *d, const char *ignore) 74{ 75 int result = 0; 76 struct dirent *de; 77 int dfd; 78 79 dfd = dirfd(d); 80 81 if (dfd < 0) return -1; 82 83 while ((de = readdir(d))) { 84 const char *name = de->d_name; 85 86 /* skip the ignore name if provided */ 87 if (ignore && !strcmp(name, ignore)) continue; 88 89 if (de->d_type == DT_DIR) { 90 int r, subfd; 91 DIR *subdir; 92 93 /* always skip "." and ".." */ 94 if (name[0] == '.') { 95 if (name[1] == 0) continue; 96 if ((name[1] == '.') && (name[2] == 0)) continue; 97 } 98 99 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 100 if (subfd < 0) { 101 result = -1; 102 continue; 103 } 104 subdir = fdopendir(subfd); 105 if (subdir == NULL) { 106 close(subfd); 107 result = -1; 108 continue; 109 } 110 if (_delete_dir_contents(subdir, 0)) { 111 result = -1; 112 } 113 closedir(subdir); 114 if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) { 115 result = -1; 116 } 117 } else { 118 if (unlinkat(dfd, name, 0) < 0) { 119 result = -1; 120 } 121 } 122 } 123 124 return result; 125} 126 127int delete_dir_contents(const char *pathname, 128 int also_delete_dir, 129 const char *ignore) 130{ 131 int res = 0; 132 DIR *d; 133 134 d = opendir(pathname); 135 if (d == NULL) { 136 return -errno; 137 } 138 res = _delete_dir_contents(d, ignore); 139 closedir(d); 140 if (also_delete_dir) { 141 if (rmdir(pathname)) { 142 res = -1; 143 } 144 } 145 return res; 146} 147 148int delete_dir_contents_fd(int dfd, const char *name) 149{ 150 int fd, res; 151 DIR *d; 152 153 fd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 154 if (fd < 0) { 155 return -1; 156 } 157 d = fdopendir(fd); 158 if (d == NULL) { 159 close(fd); 160 return -1; 161 } 162 res = _delete_dir_contents(d, 0); 163 closedir(d); 164 return res; 165} 166