• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.cts.releaseparser;
18 
19 import com.android.cts.releaseparser.ReleaseProto.*;
20 
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileReader;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30 
31 public class RcParser extends FileParser {
32     private static String OPTION_CLASS = "class ";
33     private static String OPTION_USER = "user ";
34     private static String OPTION_GROUP = "group ";
35     private static String OPTION_WRITEPID = "writepid ";
36     private static String SECTION_SERVICE = "service";
37     private static String SECTION_IMPORT = "import";
38 
39     private Entry.EntryType mType;
40     private List<Service> mServices;
41     private List<String> mImportRc;
42 
RcParser(File file)43     public RcParser(File file) {
44         super(file);
45     }
46 
47     @Override
getType()48     public Entry.EntryType getType() {
49         if (mType == null) {
50             parseFile();
51         }
52         return mType;
53     }
54 
55     @Override
setAdditionalInfo()56     public void setAdditionalInfo() {
57         getFileEntryBuilder().addAllServices(getServiceList());
58     }
59 
60     @Override
getDependencies()61     public List<String> getDependencies() {
62         if (mServices == null) {
63             parseFile();
64         }
65 
66         Map<String, Integer> dependencies = new HashMap<>();
67         for (Service service : mServices) {
68             // skip /, e.g. /system/bin/sh
69             try {
70                 String file = service.getFile().substring(1);
71                 dependencies.put(file, 1);
72             } catch (Exception e) {
73                 System.err.println(
74                         "err Service " + service.getName() + " File:" + service.getFile());
75             }
76         }
77 
78         for (String importRc : mImportRc) {
79             // skip /, e.g. /init.usb.rc
80             String file = importRc.substring(1);
81             dependencies.put(file, 1);
82         }
83 
84         return new ArrayList<String>(dependencies.keySet());
85     }
86 
87     @Override
getCodeId()88     public String getCodeId() {
89         return getFileContentId();
90     }
91 
getServiceList()92     public List<Service> getServiceList() {
93         if (mServices == null) {
94             parseFile();
95         }
96         return mServices;
97     }
98 
toString()99     public String toString() {
100         return toString(mServices);
101     }
102 
toString(List<Service> services)103     public static String toString(List<Service> services) {
104         StringBuilder result = new StringBuilder();
105         for (Service service : services) {
106             result.append(
107                     String.format(
108                             "%s %s %s %s;",
109                             service.getName(),
110                             service.getClazz(),
111                             service.getUser(),
112                             service.getGroup()));
113             // System.err.println(String.format("RcParser-toString %s %s %s ", service.getName(),
114             // service.getFile(), String.join(" ", service.getArgumentsList())));
115         }
116         return result.toString();
117     }
118 
parseFile()119     private void parseFile() {
120         // rc file spec. at android/system/core/init/README.md
121         // android/system/core/init/init.cpp?q=CreateParser
122         mServices = new ArrayList<Service>();
123         mImportRc = new ArrayList<String>();
124         try {
125             FileReader fileReader = new FileReader(getFile());
126             BufferedReader buffReader = new BufferedReader(fileReader);
127 
128             String line;
129             while ((line = buffReader.readLine()) != null) {
130                 if (line.startsWith(SECTION_SERVICE)) {
131                     parseService(line, buffReader);
132                 } else if (line.startsWith(SECTION_IMPORT)) {
133                     parseImport(line);
134                 }
135             }
136             fileReader.close();
137             mType = Entry.EntryType.RC;
138         } catch (IOException e) {
139             // file is not a RC Config
140             System.err.println("RcParser err:" + getFileName() + "\n" + e.getMessage());
141             mType = super.getType();
142         }
143         // System.err.println(this.toString());
144     }
145 
parseService(String line, BufferedReader buffReader)146     private void parseService(String line, BufferedReader buffReader) throws IOException {
147         Service.Builder serviceBld = Service.newBuilder();
148         String[] phases = line.split("\\s+");
149         serviceBld.setName(phases[1]);
150         serviceBld.setFile(phases[2]);
151         if (phases.length > 3) {
152             serviceBld.addAllArguments(Arrays.asList(phases).subList(3, phases.length));
153         }
154         String sLine;
155         while ((sLine = buffReader.readLine()) != null) {
156             String sTrimLine = sLine.trim();
157             if (sTrimLine.isEmpty()) {
158                 // End of a service block
159                 break;
160             }
161             if (sTrimLine.startsWith("#")) {
162                 // Skips comment
163                 continue;
164             } else if (sTrimLine.startsWith(OPTION_CLASS)) {
165                 serviceBld.setClazz(sTrimLine.substring(OPTION_CLASS.length()));
166             } else if (sTrimLine.startsWith(OPTION_USER)) {
167                 serviceBld.setUser(sTrimLine.substring(OPTION_USER.length()));
168             } else if (sTrimLine.startsWith(OPTION_GROUP)) {
169                 serviceBld.setGroup(sTrimLine.substring(OPTION_GROUP.length()));
170             } else if (sTrimLine.startsWith(OPTION_WRITEPID)) {
171                 serviceBld.setGroup(sTrimLine.substring(OPTION_WRITEPID.length()));
172             } else {
173                 serviceBld.addOptions(sTrimLine);
174             }
175         }
176         mServices.add(serviceBld.build());
177     }
178 
parseImport(String line)179     private void parseImport(String line) {
180         // e.g.: import /init.environ.rc
181         String[] phases = line.split(" ");
182         mImportRc.add(phases[1]);
183     }
184 }
185