• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
create_pkg_path(char path[PKG_PATH_MAX],const char * prefix,const char * pkgname,const char * postfix)19 int 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 
_delete_dir_contents(DIR * d,const char * ignore)73 static 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                 LOGE("Couldn't openat %s: %s\n", name, strerror(errno));
102                 result = -1;
103                 continue;
104             }
105             subdir = fdopendir(subfd);
106             if (subdir == NULL) {
107                 LOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
108                 close(subfd);
109                 result = -1;
110                 continue;
111             }
112             if (_delete_dir_contents(subdir, 0)) {
113                 result = -1;
114             }
115             closedir(subdir);
116             if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
117                 LOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
118                 result = -1;
119             }
120         } else {
121             if (unlinkat(dfd, name, 0) < 0) {
122                 LOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
123                 result = -1;
124             }
125         }
126     }
127 
128     return result;
129 }
130 
delete_dir_contents(const char * pathname,int also_delete_dir,const char * ignore)131 int delete_dir_contents(const char *pathname,
132                         int also_delete_dir,
133                         const char *ignore)
134 {
135     int res = 0;
136     DIR *d;
137 
138     d = opendir(pathname);
139     if (d == NULL) {
140         LOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
141         return -errno;
142     }
143     res = _delete_dir_contents(d, ignore);
144     closedir(d);
145     if (also_delete_dir) {
146         if (rmdir(pathname)) {
147             LOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
148             res = -1;
149         }
150     }
151     return res;
152 }
153 
delete_dir_contents_fd(int dfd,const char * name)154 int delete_dir_contents_fd(int dfd, const char *name)
155 {
156     int fd, res;
157     DIR *d;
158 
159     fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
160     if (fd < 0) {
161         LOGE("Couldn't openat %s: %s\n", name, strerror(errno));
162         return -1;
163     }
164     d = fdopendir(fd);
165     if (d == NULL) {
166         LOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
167         close(fd);
168         return -1;
169     }
170     res = _delete_dir_contents(d, 0);
171     closedir(d);
172     return res;
173 }
174