1 /* 2 * Copyright (C) 2009 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 <stdio.h> 18 #include <unistd.h> 19 #include <stdlib.h> 20 21 #include "edify/expr.h" 22 #include "updater.h" 23 #include "install.h" 24 #include "blockimg.h" 25 #include "minzip/Zip.h" 26 #include "minzip/SysUtil.h" 27 28 // Generated by the makefile, this function defines the 29 // RegisterDeviceExtensions() function, which calls all the 30 // registration functions for device-specific extensions. 31 #include "register.inc" 32 33 // Where in the package we expect to find the edify script to execute. 34 // (Note it's "updateR-script", not the older "update-script".) 35 #define SCRIPT_NAME "META-INF/com/google/android/updater-script" 36 37 struct selabel_handle *sehandle; 38 39 int main(int argc, char** argv) { 40 // Various things log information to stdout or stderr more or less 41 // at random (though we've tried to standardize on stdout). The 42 // log file makes more sense if buffering is turned off so things 43 // appear in the right order. 44 setbuf(stdout, NULL); 45 setbuf(stderr, NULL); 46 47 if (argc != 4) { 48 printf("unexpected number of arguments (%d)\n", argc); 49 return 1; 50 } 51 52 char* version = argv[1]; 53 if ((version[0] != '1' && version[0] != '2' && version[0] != '3') || 54 version[1] != '\0') { 55 // We support version 1, 2, or 3. 56 printf("wrong updater binary API; expected 1, 2, or 3; " 57 "got %s\n", 58 argv[1]); 59 return 2; 60 } 61 62 // Set up the pipe for sending commands back to the parent process. 63 64 int fd = atoi(argv[2]); 65 FILE* cmd_pipe = fdopen(fd, "wb"); 66 setlinebuf(cmd_pipe); 67 68 // Extract the script from the package. 69 70 const char* package_filename = argv[3]; 71 MemMapping map; 72 if (sysMapFile(package_filename, &map) != 0) { 73 printf("failed to map package %s\n", argv[3]); 74 return 3; 75 } 76 ZipArchive za; 77 int err; 78 err = mzOpenZipArchive(map.addr, map.length, &za); 79 if (err != 0) { 80 printf("failed to open package %s: %s\n", 81 argv[3], strerror(err)); 82 return 3; 83 } 84 85 const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME); 86 if (script_entry == NULL) { 87 printf("failed to find %s in %s\n", SCRIPT_NAME, package_filename); 88 return 4; 89 } 90 91 char* script = malloc(script_entry->uncompLen+1); 92 if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) { 93 printf("failed to read script from package\n"); 94 return 5; 95 } 96 script[script_entry->uncompLen] = '\0'; 97 98 // Configure edify's functions. 99 100 RegisterBuiltins(); 101 RegisterInstallFunctions(); 102 RegisterBlockImageFunctions(); 103 RegisterDeviceExtensions(); 104 FinishRegistration(); 105 106 // Parse the script. 107 108 Expr* root; 109 int error_count = 0; 110 int error = parse_string(script, &root, &error_count); 111 if (error != 0 || error_count > 0) { 112 printf("%d parse errors\n", error_count); 113 return 6; 114 } 115 116 struct selinux_opt seopts[] = { 117 { SELABEL_OPT_PATH, "/file_contexts" } 118 }; 119 120 sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); 121 122 if (!sehandle) { 123 fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n"); 124 } 125 126 // Evaluate the parsed script. 127 128 UpdaterInfo updater_info; 129 updater_info.cmd_pipe = cmd_pipe; 130 updater_info.package_zip = &za; 131 updater_info.version = atoi(version); 132 updater_info.package_zip_addr = map.addr; 133 updater_info.package_zip_len = map.length; 134 135 State state; 136 state.cookie = &updater_info; 137 state.script = script; 138 state.errmsg = NULL; 139 140 char* result = Evaluate(&state, root); 141 if (result == NULL) { 142 if (state.errmsg == NULL) { 143 printf("script aborted (no error message)\n"); 144 fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); 145 } else { 146 printf("script aborted: %s\n", state.errmsg); 147 char* line = strtok(state.errmsg, "\n"); 148 while (line) { 149 fprintf(cmd_pipe, "ui_print %s\n", line); 150 line = strtok(NULL, "\n"); 151 } 152 fprintf(cmd_pipe, "ui_print\n"); 153 } 154 free(state.errmsg); 155 return 7; 156 } else { 157 fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); 158 free(result); 159 } 160 161 if (updater_info.package_zip) { 162 mzCloseZipArchive(updater_info.package_zip); 163 } 164 sysReleaseMap(&map); 165 free(script); 166 167 return 0; 168 } 169