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