init进程的源码文件位于system/core/init,其中解析rc文件语法的代码放在五个函数中, init_parse_config_file (init_parser.c), read_file (util.c), parse_config (init_parser.c), next_token (parser.c), lookup_keyword (init_parser.c)。下面一个一个看这几个函数的具体实现。
首先是 init_parser_config_file 函数在init的main函数中被调用
1 init_parse_config_file("/init.rc");
可以看到直接解析init.rc文件,其会import其他rc文件
函数内容如下
1 int init_parse_config_file(const char *fn) 2 { 3 char *data; 4 data = read_file(fn, 0); 5 if (!data) return -1; 6 7 parse_config(fn, data); 8 DUMP(); 9 return 0; 10 }
可以看到非常简单,先把rc文件读到内存里,再调用 parse_config 函数解析读到内存中的文件内容,最后把接触出来的数据结构dump出来。
先看读取文件内容部分
1 /* reads a file, making sure it is terminated with */ 2 void *read_file(const char *fn, unsigned *_sz) 3 { 4 char *data; 5 int sz; 6 int fd; 7 struct stat sb; 8 9 data = 0; 10 fd = open(fn, O_RDONLY); 11 if(fd < 0) return 0; 12 13 // for security reasons, disallow world-writable 14 // or group-writable files 15 if (fstat(fd, &sb) < 0) { 16 ERROR("fstat failed for '%s' ", fn); 17 goto oops; 18 } 19 if ((sb.st_mode & (S_IWGRP | S_IWOTH)) != 0) { 20 ERROR("skipping insecure file '%s' ", fn); 21 goto oops; 22 } 23 24 sz = lseek(fd, 0, SEEK_END); 25 if(sz < 0) goto oops; 26 27 if(lseek(fd, 0, SEEK_SET) != 0) goto oops; 28 29 data = (char*) malloc(sz + 2); 30 if(data == 0) goto oops; 31 32 if(read(fd, data, sz) != sz) goto oops; 33 close(fd); 34 data[sz] = ' '; 35 data[sz+1] = 0; 36 if(_sz) *_sz = sz; 37 return data; 38 39 oops: 40 close(fd); 41 if(data != 0) free(data); 42 return 0; 43 }
内容很简单,要注意两点,一是权限问题,对于可以对其他用户随意写(S_IWOTH)以及组内可写的文件,不会读取其内容;二是读出来的数据在比文件附加了两个字节,一个是换行 ' ' ,一个是NULL '