2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
28 #include <arpa/inet.h>
30 #include <sys/mount.h>
31 #include <sys/resource.h>
33 #include <linux/loop.h>
34 #include <cutils/partition_utils.h>
35 #include <sys/system_properties.h>
39 #include <cutils/probe_module.h>
43 #include <selinux/selinux.h>
44 #include <selinux/label.h>
49 #include "property_service.h"
51 #include "init_parser.h"
55 #include <private/android_filesystem_config.h>
57 #define TIMEZONE "/data/property/persist.sys.timezone"
64 #define MAX_RECUR_DEPTH 15
66 void add_environment(const char *name, const char *value);
68 extern int init_module(void *, unsigned long, const char *);
70 static int write_file(const char *path, const char *value)
74 fd = open(path, O_WRONLY|O_CREAT, 0622);
82 ret = write(fd, value, len);
83 } while (ret < 0 && errno == EINTR);
93 static int _open(const char *path)
97 fd = open(path, O_RDONLY | O_NOFOLLOW);
99 fd = open(path, O_WRONLY | O_NOFOLLOW);
104 /* chown or chmod for one item (file, directory, etc.) */
105 static int __chown_chmod_one(enum builtin_cmds action, const char *path,
106 unsigned int uid, unsigned int gid, mode_t mode)
116 if (action == DO_CHOWN) {
117 ret = fchown(fd, uid, gid);
118 } else if (action == DO_CHMOD) {
119 ret = fchmod(fd, mode);
123 int errno_copy = errno;
134 /* do chown or chmod recursively with pattern matching */
135 static int __chown_chmod_recur(enum builtin_cmds action, const char *matching_path,
136 unsigned int uid, unsigned int gid, mode_t mode,
137 const char *cur_path, int depth)
141 char* child_path = NULL;
145 if (!matching_path) {
151 if (depth > MAX_RECUR_DEPTH) {
152 /* prevent this from doing infinitely recurison */
156 dirp = opendir(cur_path);
158 while ((de = readdir(dirp))) {
159 if ((de->d_type == DT_DIR) &&
160 (de->d_name[0] == '.') &&
161 ((de->d_name[1] == '\0') ||
162 ((de->d_name[1] == '.') && (de->d_name[2] == '\0')))) {
163 /* ignore directories "." and ".." */
168 len = asprintf(&child_path, "%s/%s", cur_path, de->d_name);
171 if (de->d_type == DT_DIR) {
172 /* recurse into lowering level directory */
173 ret += __chown_chmod_recur(action, matching_path,
174 uid, gid, mode, child_path,
177 if (fnmatch(matching_path, child_path, FNM_PATHNAME) == 0) {
178 /* FNM_PATHNAME: need to have the same number of '/' */
179 ret += __chown_chmod_one(action, child_path,
187 /* failed to allocate space for child_path, */
188 /* count as one failure. */
199 static int __chown_chmod(unsigned int action, const char *path,
200 unsigned int uid, unsigned int gid, mode_t mode)
202 char* leading_path = NULL;
212 /* need wildcard matching? */
213 tmp = strchr(path, '*');
215 /* this block shorten the path for matching purpose */
217 leading_path = strdup(path);
224 /* get path before '*' */
225 tmp = strchr(leading_path, '*');
230 /* remove up to and including the last '/' */
231 tmp = strrchr(leading_path, '/');
239 ret = __chown_chmod_recur(action, path,
240 uid, gid, mode, leading_path, 0);
248 return __chown_chmod_one(action, path, uid, gid, mode);
252 static int _chown(const char *path, unsigned int uid, unsigned int gid)
254 return __chown_chmod(DO_CHOWN, path, uid, gid, 0);
257 static int _chmod(const char *path, mode_t mode)
259 return __chown_chmod(DO_CHMOD, path, -1, -1, mode);
262 static int insmod(const char *filename, char *options)
268 module = read_file(filename, &size);
272 ret = init_module(module, size, options);
279 static int setkey(struct kbentry *kbe)
283 fd = open("/dev/tty0", O_RDWR | O_SYNC);
287 ret = ioctl(fd, KDSKBENT, kbe);
293 static int __ifupdown(const char *interface, int up)
298 strlcpy(ifr.ifr_name, interface, IFNAMSIZ);
300 s = socket(AF_INET, SOCK_DGRAM, 0);
304 ret = ioctl(s, SIOCGIFFLAGS, &ifr);
310 ifr.ifr_flags |= IFF_UP;
312 ifr.ifr_flags &= ~IFF_UP;
314 ret = ioctl(s, SIOCSIFFLAGS, &ifr);
321 static void service_start_if_not_disabled(struct service *svc)
323 if (!(svc->flags & SVC_DISABLED)) {
324 service_start(svc, NULL);
328 int do_chdir(int nargs, char **args)
334 int do_chroot(int nargs, char **args)
340 int do_class_start(int nargs, char **args)
342 /* Starting a class does not start services
343 * which are explicitly disabled. They must
344 * be started individually.
346 service_for_each_class(args[1], service_start_if_not_disabled);
350 int do_class_stop(int nargs, char **args)
352 service_for_each_class(args[1], service_stop);
356 int do_class_reset(int nargs, char **args)
358 service_for_each_class(args[1], service_reset);
362 int do_domainname(int nargs, char **args)
364 return write_file("/proc/sys/kernel/domainname", args[1]);
367 int do_exec(int nargs, char **args)
372 int do_export(int nargs, char **args)
374 add_environment(args[1], args[2]);
378 int do_hostname(int nargs, char **args)
380 return write_file("/proc/sys/kernel/hostname", args[1]);
383 int do_ifup(int nargs, char **args)
385 return __ifupdown(args[1], 1);
389 static int do_insmod_inner(int nargs, char **args, int opt_len)
391 char options[opt_len + 1];
396 strcpy(options, args[2]);
397 for (i = 3; i < nargs; ++i) {
398 strcat(options, " ");
399 strcat(options, args[i]);
403 return insmod(args[1], options);
406 int do_insmod(int nargs, char **args)
412 for (i = 2; i < nargs; ++i)
413 size += strlen(args[i]) + 1;
416 return do_insmod_inner(nargs, args, size);
419 static int do_probemod_inner(int nargs, char **args, int opt_len)
421 char options[opt_len + 1];
427 strcpy(options, args[2]);
428 for (i = 3; i < nargs; ++i) {
429 strcat(options, " ");
430 strcat(options, args[i]);
434 ret = insmod_by_dep(args[1], options, NULL, 1, NULL);
436 ERROR("Couldn't probe module '%s'\n", args[1]);
440 int do_probemod(int nargs, char **args)
446 for (i = 2; i < nargs; ++i)
447 size += strlen(args[i]) + 1;
450 return do_probemod_inner(nargs, args, size);
453 int do_mkdir(int nargs, char **args)
458 /* mkdir <path> [mode] [owner] [group] */
461 mode = strtoul(args[2], 0, 8);
464 ret = make_dir(args[1], mode);
465 /* chmod in case the directory already exists */
466 if (ret == -1 && errno == EEXIST) {
467 ret = _chmod(args[1], mode);
474 uid_t uid = decode_uid(args[3]);
478 gid = decode_uid(args[4]);
481 if (_chown(args[1], uid, gid) < 0) {
485 /* chown may have cleared S_ISUID and S_ISGID, chmod again */
486 if (mode & (S_ISUID | S_ISGID)) {
487 ret = _chmod(args[1], mode);
501 { "noatime", MS_NOATIME },
502 { "noexec", MS_NOEXEC },
503 { "nosuid", MS_NOSUID },
504 { "nodev", MS_NODEV },
505 { "nodiratime", MS_NODIRATIME },
508 { "remount", MS_REMOUNT },
511 { "unbindable", MS_UNBINDABLE },
512 { "private", MS_PRIVATE },
513 { "slave", MS_SLAVE },
514 { "shared", MS_SHARED },
519 #define DATA_MNT_POINT "/data"
521 /* mount <type> <device> <path> <flags ...> <options> */
522 int do_mount(int nargs, char **args)
525 char *source, *target, *system;
526 char *options = NULL;
531 for (n = 4; n < nargs; n++) {
532 for (i = 0; mount_flags[i].name; i++) {
533 if (!strcmp(args[n], mount_flags[i].name)) {
534 flags |= mount_flags[i].flag;
539 if (!mount_flags[i].name) {
540 if (!strcmp(args[n], "wait"))
542 /* if our last argument isn't a flag, wolf it up as an option string */
543 else if (n + 1 == nargs)
552 if (!strncmp(source, "mtd@", 4)) {
553 n = mtd_name_to_number(source + 4);
558 sprintf(tmp, "/dev/block/mtdblock%d", n);
561 wait_for_file(tmp, COMMAND_RETRY_TIMEOUT);
562 if (mount(tmp, target, system, flags, options) < 0) {
567 } else if (!strncmp(source, "loop@", 5)) {
569 struct loop_info info;
571 mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
572 fd = open(source + 5, mode);
578 sprintf(tmp, "/dev/block/loop%d", n);
579 loop = open(tmp, mode);
584 /* if it is a blank loop device */
585 if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {
586 /* if it becomes our loop device */
587 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
590 if (mount(tmp, target, system, flags, options) < 0) {
591 ioctl(loop, LOOP_CLR_FD, 0);
605 ERROR("out of loopback devices");
609 wait_for_file(source, COMMAND_RETRY_TIMEOUT);
610 if (mount(source, target, system, flags, options) < 0) {
621 int do_mount_all(int nargs, char **args)
634 * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
635 * do the call in the child to provide protection to the main init
636 * process if anything goes wrong (crash or memory leak), and wait for
637 * the child to finish in the parent.
641 /* Parent. Wait for the child to return */
642 waitpid(pid, &status, 0);
643 if (WIFEXITED(status)) {
644 ret = WEXITSTATUS(status);
648 } else if (pid == 0) {
649 /* child, call fs_mgr_mount_all() */
650 klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */
651 child_ret = fs_mgr_mount_all(args[1]);
652 if (child_ret == -1) {
653 ERROR("fs_mgr_mount_all returned an error\n");
657 /* fork failed, return an error */
661 /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */
663 property_set("ro.crypto.state", "encrypted");
664 property_set("vold.decrypt", "1");
665 } else if (ret == 0) {
666 property_set("ro.crypto.state", "unencrypted");
667 /* If fs_mgr determined this is an unencrypted device, then trigger
670 action_for_each_trigger("nonencrypted", action_add_queue_tail);
676 int do_setcon(int nargs, char **args) {
678 if (is_selinux_enabled() <= 0)
680 if (setcon(args[1]) < 0) {
687 int do_setenforce(int nargs, char **args) {
689 if (is_selinux_enabled() <= 0)
691 if (security_setenforce(atoi(args[1])) < 0) {
698 int do_setkey(int nargs, char **args)
701 kbe.kb_table = strtoul(args[1], 0, 0);
702 kbe.kb_index = strtoul(args[2], 0, 0);
703 kbe.kb_value = strtoul(args[3], 0, 0);
707 int do_builtin_coldboot(int nargs, char **args)
709 if (nargs != 2 || !args[1] || *args[1] == '\0')
717 int do_setprop(int nargs, char **args)
719 const char *name = args[1];
720 const char *value = args[2];
722 property_set(name, value);
726 int do_setrlimit(int nargs, char **args)
730 resource = atoi(args[1]);
731 limit.rlim_cur = atoi(args[2]);
732 limit.rlim_max = atoi(args[3]);
733 return setrlimit(resource, &limit);
736 int do_start(int nargs, char **args)
739 svc = service_find_by_name(args[1]);
741 service_start(svc, NULL);
746 int do_stop(int nargs, char **args)
749 svc = service_find_by_name(args[1]);
756 int do_restart(int nargs, char **args)
759 svc = service_find_by_name(args[1]);
762 service_start(svc, NULL);
767 int do_trigger(int nargs, char **args)
769 action_for_each_trigger(args[1], action_add_queue_tail);
773 int do_symlink(int nargs, char **args)
775 return symlink(args[1], args[2]);
778 int do_rm(int nargs, char **args)
780 return unlink(args[1]);
783 int do_rmdir(int nargs, char **args)
785 return rmdir(args[1]);
788 int do_sysclktz(int nargs, char **args)
796 char const *hwtime_mode;
802 memset(&tz, 0, sizeof(tz));
803 memset(&tv, 0, sizeof(tv));
804 memset(&tm, 0, sizeof(tm));
806 if (!strcmp(args[1], "0")) {
807 tz.tz_minuteswest = atoi(args[1]);
808 if (settimeofday(NULL, &tz))
813 if (gettimeofday(&tv, NULL))
815 hwtime_mode = property_get("ro.rtc_local_time");
816 if (hwtime_mode && !strcmp(hwtime_mode, "1")
817 && !strcmp(args[1], "1")) {
819 /* Notify kernel that hwtime use local time */
820 write_file("/sys/class/misc/alarm/rtc_local_time",
823 * If ro.hwtime.mode is local, set system time
824 * and saved system zone in case of network not
825 * available and auto syncing time not available.
827 if (access(TIMEZONE, 0) == 0) {
828 fp = fopen(TIMEZONE, "r+");
832 if (getline(&line, &len, fp) == -1)
833 tz.tz_minuteswest = 0;
835 /* Hack to get timezone. */
836 for (len = 0; *(line+len) != '\n' && *(line+len) != 0; len++);
838 property_set("persist.sys.timezone", line);
840 localtime_r(&t, &tm);
841 tz.tz_minuteswest = -(tm.tm_gmtoff / 60);
847 tz.tz_minuteswest = 0;
850 * At this moment, system time should be local
851 * time too, set it back to utc which linux required.
853 tv.tv_sec += tz.tz_minuteswest * 60;
854 if (settimeofday(&tv, &tz))
862 int do_write(int nargs, char **args)
864 const char *path = args[1];
865 const char *value = args[2];
867 return write_file(path, value);
870 int do_copy(int nargs, char **args)
874 int fd1 = -1, fd2 = -1;
882 if (stat(args[1], &info) < 0)
885 if ((fd1 = open(args[1], O_RDONLY)) < 0)
888 if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
891 if (!(buffer = malloc(info.st_size)))
897 rc = read(fd1, p, brtr);
909 rc = write(fd2, p, brtw);
932 int do_chown(int nargs, char **args) {
933 /* GID is optional. */
935 if (_chown(args[2], decode_uid(args[1]), -1) < 0)
937 } else if (nargs == 4) {
938 if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0)
946 static mode_t get_mode(const char *s) {
949 if (*s >= '0' && *s <= '7') {
950 mode = (mode<<3) | (*s-'0');
959 int do_chmod(int nargs, char **args) {
960 mode_t mode = get_mode(args[1]);
961 if (_chmod(args[2], mode) < 0) {
967 int do_restorecon(int nargs, char **args) {
970 for (i = 1; i < nargs; i++) {
971 if (restorecon(args[i]) < 0)
977 int do_setsebool(int nargs, char **args) {
979 SELboolean *b = alloca(nargs * sizeof(SELboolean));
983 if (is_selinux_enabled() <= 0)
986 for (i = 1; i < nargs; i++) {
987 char *name = args[i];
988 v = strchr(name, '=');
990 ERROR("setsebool: argument %s had no =\n", name);
995 if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on"))
997 else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off"))
1000 ERROR("setsebool: invalid value %s\n", v);
1005 if (security_set_boolean_list(nargs - 1, b, 0) < 0)
1011 int do_loglevel(int nargs, char **args) {
1013 klog_set_level(atoi(args[1]));
1019 int do_load_persist_props(int nargs, char **args) {
1021 load_persist_props();
1027 int do_wait(int nargs, char **args)
1030 return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT);
1031 } else if (nargs == 3) {
1032 return wait_for_file(args[1], atoi(args[2]));
1037 int do_readprops(int nargs, char **args)
1040 return load_properties_from_file(args[1]);