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