• 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 <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <linux/kd.h>
24 #include <errno.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <linux/if.h>
28 #include <arpa/inet.h>
29 #include <stdlib.h>
30 #include <sys/mount.h>
31 #include <sys/resource.h>
32 #include <linux/loop.h>
33 
34 #include "init.h"
35 #include "keywords.h"
36 #include "property_service.h"
37 #include "devices.h"
38 #include "init_parser.h"
39 #include "util.h"
40 #include "log.h"
41 
42 #include <private/android_filesystem_config.h>
43 
44 void add_environment(const char *name, const char *value);
45 
46 extern int init_module(void *, unsigned long, const char *);
47 
write_file(const char * path,const char * value)48 static int write_file(const char *path, const char *value)
49 {
50     int fd, ret, len;
51 
52     fd = open(path, O_WRONLY|O_CREAT, 0622);
53 
54     if (fd < 0)
55         return -errno;
56 
57     len = strlen(value);
58 
59     do {
60         ret = write(fd, value, len);
61     } while (ret < 0 && errno == EINTR);
62 
63     close(fd);
64     if (ret < 0) {
65         return -errno;
66     } else {
67         return 0;
68     }
69 }
70 
insmod(const char * filename,char * options)71 static int insmod(const char *filename, char *options)
72 {
73     void *module;
74     unsigned size;
75     int ret;
76 
77     module = read_file(filename, &size);
78     if (!module)
79         return -1;
80 
81     ret = init_module(module, size, options);
82 
83     free(module);
84 
85     return ret;
86 }
87 
setkey(struct kbentry * kbe)88 static int setkey(struct kbentry *kbe)
89 {
90     int fd, ret;
91 
92     fd = open("/dev/tty0", O_RDWR | O_SYNC);
93     if (fd < 0)
94         return -1;
95 
96     ret = ioctl(fd, KDSKBENT, kbe);
97 
98     close(fd);
99     return ret;
100 }
101 
__ifupdown(const char * interface,int up)102 static int __ifupdown(const char *interface, int up)
103 {
104     struct ifreq ifr;
105     int s, ret;
106 
107     strlcpy(ifr.ifr_name, interface, IFNAMSIZ);
108 
109     s = socket(AF_INET, SOCK_DGRAM, 0);
110     if (s < 0)
111         return -1;
112 
113     ret = ioctl(s, SIOCGIFFLAGS, &ifr);
114     if (ret < 0) {
115         goto done;
116     }
117 
118     if (up)
119         ifr.ifr_flags |= IFF_UP;
120     else
121         ifr.ifr_flags &= ~IFF_UP;
122 
123     ret = ioctl(s, SIOCSIFFLAGS, &ifr);
124 
125 done:
126     close(s);
127     return ret;
128 }
129 
service_start_if_not_disabled(struct service * svc)130 static void service_start_if_not_disabled(struct service *svc)
131 {
132     if (!(svc->flags & SVC_DISABLED)) {
133         service_start(svc, NULL);
134     }
135 }
136 
do_chdir(int nargs,char ** args)137 int do_chdir(int nargs, char **args)
138 {
139     chdir(args[1]);
140     return 0;
141 }
142 
do_chroot(int nargs,char ** args)143 int do_chroot(int nargs, char **args)
144 {
145     chroot(args[1]);
146     return 0;
147 }
148 
do_class_start(int nargs,char ** args)149 int do_class_start(int nargs, char **args)
150 {
151         /* Starting a class does not start services
152          * which are explicitly disabled.  They must
153          * be started individually.
154          */
155     service_for_each_class(args[1], service_start_if_not_disabled);
156     return 0;
157 }
158 
do_class_stop(int nargs,char ** args)159 int do_class_stop(int nargs, char **args)
160 {
161     service_for_each_class(args[1], service_stop);
162     return 0;
163 }
164 
do_domainname(int nargs,char ** args)165 int do_domainname(int nargs, char **args)
166 {
167     return write_file("/proc/sys/kernel/domainname", args[1]);
168 }
169 
do_exec(int nargs,char ** args)170 int do_exec(int nargs, char **args)
171 {
172     return -1;
173 }
174 
do_export(int nargs,char ** args)175 int do_export(int nargs, char **args)
176 {
177     add_environment(args[1], args[2]);
178     return 0;
179 }
180 
do_hostname(int nargs,char ** args)181 int do_hostname(int nargs, char **args)
182 {
183     return write_file("/proc/sys/kernel/hostname", args[1]);
184 }
185 
do_ifup(int nargs,char ** args)186 int do_ifup(int nargs, char **args)
187 {
188     return __ifupdown(args[1], 1);
189 }
190 
191 
do_insmod_inner(int nargs,char ** args,int opt_len)192 static int do_insmod_inner(int nargs, char **args, int opt_len)
193 {
194     char options[opt_len + 1];
195     int i;
196 
197     options[0] = '\0';
198     if (nargs > 2) {
199         strcpy(options, args[2]);
200         for (i = 3; i < nargs; ++i) {
201             strcat(options, " ");
202             strcat(options, args[i]);
203         }
204     }
205 
206     return insmod(args[1], options);
207 }
208 
do_insmod(int nargs,char ** args)209 int do_insmod(int nargs, char **args)
210 {
211     int i;
212     int size = 0;
213 
214     if (nargs > 2) {
215         for (i = 2; i < nargs; ++i)
216             size += strlen(args[i]) + 1;
217     }
218 
219     return do_insmod_inner(nargs, args, size);
220 }
221 
do_import(int nargs,char ** args)222 int do_import(int nargs, char **args)
223 {
224     return init_parse_config_file(args[1]);
225 }
226 
do_mkdir(int nargs,char ** args)227 int do_mkdir(int nargs, char **args)
228 {
229     mode_t mode = 0755;
230 
231     /* mkdir <path> [mode] [owner] [group] */
232 
233     if (nargs >= 3) {
234         mode = strtoul(args[2], 0, 8);
235     }
236 
237     if (mkdir(args[1], mode)) {
238         return -errno;
239     }
240 
241     if (nargs >= 4) {
242         uid_t uid = decode_uid(args[3]);
243         gid_t gid = -1;
244 
245         if (nargs == 5) {
246             gid = decode_uid(args[4]);
247         }
248 
249         if (chown(args[1], uid, gid)) {
250             return -errno;
251         }
252     }
253 
254     return 0;
255 }
256 
257 static struct {
258     const char *name;
259     unsigned flag;
260 } mount_flags[] = {
261     { "move",       MS_MOVE },
262     { "noatime",    MS_NOATIME },
263     { "nosuid",     MS_NOSUID },
264     { "nodev",      MS_NODEV },
265     { "nodiratime", MS_NODIRATIME },
266     { "ro",         MS_RDONLY },
267     { "rw",         0 },
268     { "remount",    MS_REMOUNT },
269     { "defaults",   0 },
270     { 0,            0 },
271 };
272 
273 /* mount <type> <device> <path> <flags ...> <options> */
do_mount(int nargs,char ** args)274 int do_mount(int nargs, char **args)
275 {
276     char tmp[64];
277     char *source, *target, *system;
278     char *options = NULL;
279     unsigned flags = 0;
280     int n, i;
281     int wait = 0;
282 
283     for (n = 4; n < nargs; n++) {
284         for (i = 0; mount_flags[i].name; i++) {
285             if (!strcmp(args[n], mount_flags[i].name)) {
286                 flags |= mount_flags[i].flag;
287                 break;
288             }
289         }
290 
291         if (!mount_flags[i].name) {
292             if (!strcmp(args[n], "wait"))
293                 wait = 1;
294             /* if our last argument isn't a flag, wolf it up as an option string */
295             else if (n + 1 == nargs)
296                 options = args[n];
297         }
298     }
299 
300     system = args[1];
301     source = args[2];
302     target = args[3];
303 
304     if (!strncmp(source, "mtd@", 4)) {
305         n = mtd_name_to_number(source + 4);
306         if (n < 0) {
307             return -1;
308         }
309 
310         sprintf(tmp, "/dev/block/mtdblock%d", n);
311 
312         if (wait)
313             wait_for_file(tmp, COMMAND_RETRY_TIMEOUT);
314         if (mount(tmp, target, system, flags, options) < 0) {
315             return -1;
316         }
317 
318         return 0;
319     } else if (!strncmp(source, "loop@", 5)) {
320         int mode, loop, fd;
321         struct loop_info info;
322 
323         mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
324         fd = open(source + 5, mode);
325         if (fd < 0) {
326             return -1;
327         }
328 
329         for (n = 0; ; n++) {
330             sprintf(tmp, "/dev/block/loop%d", n);
331             loop = open(tmp, mode);
332             if (loop < 0) {
333                 return -1;
334             }
335 
336             /* if it is a blank loop device */
337             if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
338                 /* if it becomes our loop device */
339                 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
340                     close(fd);
341 
342                     if (mount(tmp, target, system, flags, options) < 0) {
343                         ioctl(loop, LOOP_CLR_FD, 0);
344                         close(loop);
345                         return -1;
346                     }
347 
348                     close(loop);
349                     return 0;
350                 }
351             }
352 
353             close(loop);
354         }
355 
356         close(fd);
357         ERROR("out of loopback devices");
358         return -1;
359     } else {
360         if (wait)
361             wait_for_file(source, COMMAND_RETRY_TIMEOUT);
362         if (mount(source, target, system, flags, options) < 0) {
363             return -1;
364         }
365 
366         return 0;
367     }
368 }
369 
do_setkey(int nargs,char ** args)370 int do_setkey(int nargs, char **args)
371 {
372     struct kbentry kbe;
373     kbe.kb_table = strtoul(args[1], 0, 0);
374     kbe.kb_index = strtoul(args[2], 0, 0);
375     kbe.kb_value = strtoul(args[3], 0, 0);
376     return setkey(&kbe);
377 }
378 
do_setprop(int nargs,char ** args)379 int do_setprop(int nargs, char **args)
380 {
381     property_set(args[1], args[2]);
382     return 0;
383 }
384 
do_setrlimit(int nargs,char ** args)385 int do_setrlimit(int nargs, char **args)
386 {
387     struct rlimit limit;
388     int resource;
389     resource = atoi(args[1]);
390     limit.rlim_cur = atoi(args[2]);
391     limit.rlim_max = atoi(args[3]);
392     return setrlimit(resource, &limit);
393 }
394 
do_start(int nargs,char ** args)395 int do_start(int nargs, char **args)
396 {
397     struct service *svc;
398     svc = service_find_by_name(args[1]);
399     if (svc) {
400         service_start(svc, NULL);
401     }
402     return 0;
403 }
404 
do_stop(int nargs,char ** args)405 int do_stop(int nargs, char **args)
406 {
407     struct service *svc;
408     svc = service_find_by_name(args[1]);
409     if (svc) {
410         service_stop(svc);
411     }
412     return 0;
413 }
414 
do_restart(int nargs,char ** args)415 int do_restart(int nargs, char **args)
416 {
417     struct service *svc;
418     svc = service_find_by_name(args[1]);
419     if (svc) {
420         service_stop(svc);
421         service_start(svc, NULL);
422     }
423     return 0;
424 }
425 
do_trigger(int nargs,char ** args)426 int do_trigger(int nargs, char **args)
427 {
428     action_for_each_trigger(args[1], action_add_queue_tail);
429     return 0;
430 }
431 
do_symlink(int nargs,char ** args)432 int do_symlink(int nargs, char **args)
433 {
434     return symlink(args[1], args[2]);
435 }
436 
do_sysclktz(int nargs,char ** args)437 int do_sysclktz(int nargs, char **args)
438 {
439     struct timezone tz;
440 
441     if (nargs != 2)
442         return -1;
443 
444     memset(&tz, 0, sizeof(tz));
445     tz.tz_minuteswest = atoi(args[1]);
446     if (settimeofday(NULL, &tz))
447         return -1;
448     return 0;
449 }
450 
do_write(int nargs,char ** args)451 int do_write(int nargs, char **args)
452 {
453     return write_file(args[1], args[2]);
454 }
455 
do_copy(int nargs,char ** args)456 int do_copy(int nargs, char **args)
457 {
458     char *buffer = NULL;
459     int rc = 0;
460     int fd1 = -1, fd2 = -1;
461     struct stat info;
462     int brtw, brtr;
463     char *p;
464 
465     if (nargs != 3)
466         return -1;
467 
468     if (stat(args[1], &info) < 0)
469         return -1;
470 
471     if ((fd1 = open(args[1], O_RDONLY)) < 0)
472         goto out_err;
473 
474     if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
475         goto out_err;
476 
477     if (!(buffer = malloc(info.st_size)))
478         goto out_err;
479 
480     p = buffer;
481     brtr = info.st_size;
482     while(brtr) {
483         rc = read(fd1, p, brtr);
484         if (rc < 0)
485             goto out_err;
486         if (rc == 0)
487             break;
488         p += rc;
489         brtr -= rc;
490     }
491 
492     p = buffer;
493     brtw = info.st_size;
494     while(brtw) {
495         rc = write(fd2, p, brtw);
496         if (rc < 0)
497             goto out_err;
498         if (rc == 0)
499             break;
500         p += rc;
501         brtw -= rc;
502     }
503 
504     rc = 0;
505     goto out;
506 out_err:
507     rc = -1;
508 out:
509     if (buffer)
510         free(buffer);
511     if (fd1 >= 0)
512         close(fd1);
513     if (fd2 >= 0)
514         close(fd2);
515     return rc;
516 }
517 
do_chown(int nargs,char ** args)518 int do_chown(int nargs, char **args) {
519     /* GID is optional. */
520     if (nargs == 3) {
521         if (chown(args[2], decode_uid(args[1]), -1) < 0)
522             return -errno;
523     } else if (nargs == 4) {
524         if (chown(args[3], decode_uid(args[1]), decode_uid(args[2])))
525             return -errno;
526     } else {
527         return -1;
528     }
529     return 0;
530 }
531 
get_mode(const char * s)532 static mode_t get_mode(const char *s) {
533     mode_t mode = 0;
534     while (*s) {
535         if (*s >= '0' && *s <= '7') {
536             mode = (mode<<3) | (*s-'0');
537         } else {
538             return -1;
539         }
540         s++;
541     }
542     return mode;
543 }
544 
do_chmod(int nargs,char ** args)545 int do_chmod(int nargs, char **args) {
546     mode_t mode = get_mode(args[1]);
547     if (chmod(args[2], mode) < 0) {
548         return -errno;
549     }
550     return 0;
551 }
552 
do_loglevel(int nargs,char ** args)553 int do_loglevel(int nargs, char **args) {
554     if (nargs == 2) {
555         log_set_level(atoi(args[1]));
556         return 0;
557     }
558     return -1;
559 }
560 
do_wait(int nargs,char ** args)561 int do_wait(int nargs, char **args)
562 {
563     if (nargs == 2) {
564         return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT);
565     }
566     return -1;
567 }
568