• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 <stdarg.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <fcntl.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <time.h>
25 
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30 
31 /* for ANDROID_SOCKET_* */
32 #include <cutils/sockets.h>
33 
34 #include <private/android_filesystem_config.h>
35 
36 #include "log.h"
37 #include "list.h"
38 #include "util.h"
39 
40 static int log_fd = -1;
41 /* Inital log level before init.rc is parsed and this this is reset. */
42 static int log_level = LOG_DEFAULT_LEVEL;
43 
44 
log_set_level(int level)45 void log_set_level(int level) {
46     log_level = level;
47 }
48 
log_init(void)49 void log_init(void)
50 {
51     static const char *name = "/dev/__kmsg__";
52     if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
53         log_fd = open(name, O_WRONLY);
54         fcntl(log_fd, F_SETFD, FD_CLOEXEC);
55         unlink(name);
56     }
57 }
58 
59 #define LOG_BUF_MAX 512
60 
log_write(int level,const char * fmt,...)61 void log_write(int level, const char *fmt, ...)
62 {
63     char buf[LOG_BUF_MAX];
64     va_list ap;
65 
66     if (level > log_level) return;
67     if (log_fd < 0) return;
68 
69     va_start(ap, fmt);
70     vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
71     buf[LOG_BUF_MAX - 1] = 0;
72     va_end(ap);
73     write(log_fd, buf, strlen(buf));
74 }
75 
76 /*
77  * android_name_to_id - returns the integer uid/gid associated with the given
78  * name, or -1U on error.
79  */
android_name_to_id(const char * name)80 static unsigned int android_name_to_id(const char *name)
81 {
82     struct android_id_info *info = android_ids;
83     unsigned int n;
84 
85     for (n = 0; n < android_id_count; n++) {
86         if (!strcmp(info[n].name, name))
87             return info[n].aid;
88     }
89 
90     return -1U;
91 }
92 
93 /*
94  * decode_uid - decodes and returns the given string, which can be either the
95  * numeric or name representation, into the integer uid or gid. Returns -1U on
96  * error.
97  */
decode_uid(const char * s)98 unsigned int decode_uid(const char *s)
99 {
100     unsigned int v;
101 
102     if (!s || *s == '\0')
103         return -1U;
104     if (isalpha(s[0]))
105         return android_name_to_id(s);
106 
107     errno = 0;
108     v = (unsigned int) strtoul(s, 0, 0);
109     if (errno)
110         return -1U;
111     return v;
112 }
113 
114 /*
115  * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
116  * ("/dev/socket") as dictated in init.rc. This socket is inherited by the
117  * daemon. We communicate the file descriptor's value via the environment
118  * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
119  */
create_socket(const char * name,int type,mode_t perm,uid_t uid,gid_t gid)120 int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
121 {
122     struct sockaddr_un addr;
123     int fd, ret;
124 
125     fd = socket(PF_UNIX, type, 0);
126     if (fd < 0) {
127         ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
128         return -1;
129     }
130 
131     memset(&addr, 0 , sizeof(addr));
132     addr.sun_family = AF_UNIX;
133     snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
134              name);
135 
136     ret = unlink(addr.sun_path);
137     if (ret != 0 && errno != ENOENT) {
138         ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
139         goto out_close;
140     }
141 
142     ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
143     if (ret) {
144         ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
145         goto out_unlink;
146     }
147 
148     chown(addr.sun_path, uid, gid);
149     chmod(addr.sun_path, perm);
150 
151     INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
152          addr.sun_path, perm, uid, gid);
153 
154     return fd;
155 
156 out_unlink:
157     unlink(addr.sun_path);
158 out_close:
159     close(fd);
160     return -1;
161 }
162 
163 /* reads a file, making sure it is terminated with \n \0 */
read_file(const char * fn,unsigned * _sz)164 void *read_file(const char *fn, unsigned *_sz)
165 {
166     char *data;
167     int sz;
168     int fd;
169 
170     data = 0;
171     fd = open(fn, O_RDONLY);
172     if(fd < 0) return 0;
173 
174     sz = lseek(fd, 0, SEEK_END);
175     if(sz < 0) goto oops;
176 
177     if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
178 
179     data = (char*) malloc(sz + 2);
180     if(data == 0) goto oops;
181 
182     if(read(fd, data, sz) != sz) goto oops;
183     close(fd);
184     data[sz] = '\n';
185     data[sz+1] = 0;
186     if(_sz) *_sz = sz;
187     return data;
188 
189 oops:
190     close(fd);
191     if(data != 0) free(data);
192     return 0;
193 }
194 
list_init(struct listnode * node)195 void list_init(struct listnode *node)
196 {
197     node->next = node;
198     node->prev = node;
199 }
200 
list_add_tail(struct listnode * head,struct listnode * item)201 void list_add_tail(struct listnode *head, struct listnode *item)
202 {
203     item->next = head;
204     item->prev = head->prev;
205     head->prev->next = item;
206     head->prev = item;
207 }
208 
list_remove(struct listnode * item)209 void list_remove(struct listnode *item)
210 {
211     item->next->prev = item->prev;
212     item->prev->next = item->next;
213 }
214 
215 #define MAX_MTD_PARTITIONS 16
216 
217 static struct {
218     char name[16];
219     int number;
220 } mtd_part_map[MAX_MTD_PARTITIONS];
221 
222 static int mtd_part_count = -1;
223 
find_mtd_partitions(void)224 static void find_mtd_partitions(void)
225 {
226     int fd;
227     char buf[1024];
228     char *pmtdbufp;
229     ssize_t pmtdsize;
230     int r;
231 
232     fd = open("/proc/mtd", O_RDONLY);
233     if (fd < 0)
234         return;
235 
236     buf[sizeof(buf) - 1] = '\0';
237     pmtdsize = read(fd, buf, sizeof(buf) - 1);
238     pmtdbufp = buf;
239     while (pmtdsize > 0) {
240         int mtdnum, mtdsize, mtderasesize;
241         char mtdname[16];
242         mtdname[0] = '\0';
243         mtdnum = -1;
244         r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
245                    &mtdnum, &mtdsize, &mtderasesize, mtdname);
246         if ((r == 4) && (mtdname[0] == '"')) {
247             char *x = strchr(mtdname + 1, '"');
248             if (x) {
249                 *x = 0;
250             }
251             INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
252             if (mtd_part_count < MAX_MTD_PARTITIONS) {
253                 strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
254                 mtd_part_map[mtd_part_count].number = mtdnum;
255                 mtd_part_count++;
256             } else {
257                 ERROR("too many mtd partitions\n");
258             }
259         }
260         while (pmtdsize > 0 && *pmtdbufp != '\n') {
261             pmtdbufp++;
262             pmtdsize--;
263         }
264         if (pmtdsize > 0) {
265             pmtdbufp++;
266             pmtdsize--;
267         }
268     }
269     close(fd);
270 }
271 
mtd_name_to_number(const char * name)272 int mtd_name_to_number(const char *name)
273 {
274     int n;
275     if (mtd_part_count < 0) {
276         mtd_part_count = 0;
277         find_mtd_partitions();
278     }
279     for (n = 0; n < mtd_part_count; n++) {
280         if (!strcmp(name, mtd_part_map[n].name)) {
281             return mtd_part_map[n].number;
282         }
283     }
284     return -1;
285 }
286 
287 /*
288  * gettime() - returns the time in seconds of the system's monotonic clock or
289  * zero on error.
290  */
gettime(void)291 time_t gettime(void)
292 {
293     struct timespec ts;
294     int ret;
295 
296     ret = clock_gettime(CLOCK_MONOTONIC, &ts);
297     if (ret < 0) {
298         ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
299         return 0;
300     }
301 
302     return ts.tv_sec;
303 }
304 
mkdir_recursive(const char * pathname,mode_t mode)305 int mkdir_recursive(const char *pathname, mode_t mode)
306 {
307     char buf[128];
308     const char *slash;
309     const char *p = pathname;
310     int width;
311     int ret;
312     struct stat info;
313 
314     while ((slash = strchr(p, '/')) != NULL) {
315         width = slash - pathname;
316         p = slash + 1;
317         if (width < 0)
318             break;
319         if (width == 0)
320             continue;
321         if ((unsigned int)width > sizeof(buf) - 1) {
322             ERROR("path too long for mkdir_recursive\n");
323             return -1;
324         }
325         memcpy(buf, pathname, width);
326         buf[width] = 0;
327         if (stat(buf, &info) != 0) {
328             ret = mkdir(buf, mode);
329             if (ret && errno != EEXIST)
330                 return ret;
331         }
332     }
333     ret = mkdir(pathname, mode);
334     if (ret && errno != EEXIST)
335         return ret;
336     return 0;
337 }
338 
sanitize(char * s)339 void sanitize(char *s)
340 {
341     if (!s)
342         return;
343     while (isalnum(*s))
344         s++;
345     *s = 0;
346 }
make_link(const char * oldpath,const char * newpath)347 void make_link(const char *oldpath, const char *newpath)
348 {
349     int ret;
350     char buf[256];
351     char *slash;
352     int width;
353 
354     slash = strrchr(newpath, '/');
355     if (!slash)
356         return;
357     width = slash - newpath;
358     if (width <= 0 || width > (int)sizeof(buf) - 1)
359         return;
360     memcpy(buf, newpath, width);
361     buf[width] = 0;
362     ret = mkdir_recursive(buf, 0755);
363     if (ret)
364         ERROR("Failed to create directory %s: %s (%d)\n", buf, strerror(errno), errno);
365 
366     ret = symlink(oldpath, newpath);
367     if (ret && errno != EEXIST)
368         ERROR("Failed to symlink %s to %s: %s (%d)\n", oldpath, newpath, strerror(errno), errno);
369 }
370 
remove_link(const char * oldpath,const char * newpath)371 void remove_link(const char *oldpath, const char *newpath)
372 {
373     char path[256];
374     ssize_t ret;
375     ret = readlink(newpath, path, sizeof(path) - 1);
376     if (ret <= 0)
377         return;
378     path[ret] = 0;
379     if (!strcmp(path, oldpath))
380         unlink(newpath);
381 }
382 
wait_for_file(const char * filename,int timeout)383 int wait_for_file(const char *filename, int timeout)
384 {
385     struct stat info;
386     time_t timeout_time = gettime() + timeout;
387     int ret = -1;
388 
389     while (gettime() < timeout_time && ((ret = stat(filename, &info)) < 0))
390         usleep(10000);
391 
392     return ret;
393 }
394 
open_devnull_stdio(void)395 void open_devnull_stdio(void)
396 {
397     int fd;
398     static const char *name = "/dev/__null__";
399     if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
400         fd = open(name, O_RDWR);
401         unlink(name);
402         if (fd >= 0) {
403             dup2(fd, 0);
404             dup2(fd, 1);
405             dup2(fd, 2);
406             if (fd > 2) {
407                 close(fd);
408             }
409             return;
410         }
411     }
412 
413     exit(1);
414 }
415 
get_hardware_name(char * hardware,unsigned int * revision)416 void get_hardware_name(char *hardware, unsigned int *revision)
417 {
418     char data[1024];
419     int fd, n;
420     char *x, *hw, *rev;
421 
422     /* Hardware string was provided on kernel command line */
423     if (hardware[0])
424         return;
425 
426     fd = open("/proc/cpuinfo", O_RDONLY);
427     if (fd < 0) return;
428 
429     n = read(fd, data, 1023);
430     close(fd);
431     if (n < 0) return;
432 
433     data[n] = 0;
434     hw = strstr(data, "\nHardware");
435     rev = strstr(data, "\nRevision");
436 
437     if (hw) {
438         x = strstr(hw, ": ");
439         if (x) {
440             x += 2;
441             n = 0;
442             while (*x && !isspace(*x)) {
443                 hardware[n++] = tolower(*x);
444                 x++;
445                 if (n == 31) break;
446             }
447             hardware[n] = 0;
448         }
449     }
450 
451     if (rev) {
452         x = strstr(rev, ": ");
453         if (x) {
454             *revision = strtoul(x + 2, 0, 16);
455         }
456     }
457 }
458