android_bootable_recovery/edifyscripting.c

300 lines
7.9 KiB
C
Raw Normal View History

// Copyright ClockworkMod, LLC. Reference and porting purposes only. Usage of the extendedcommand API
// is restricted to those granted explicit permission, or by use of the ROM Manager Recovery API.
// https://github.com/koush/TestRomManager
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/reboot.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/limits.h>
#include <dirent.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/wait.h>
#include "bootloader.h"
#include "common.h"
#include "cutils/properties.h"
#include "firmware.h"
#include "install.h"
#include "minui/minui.h"
#include "minzip/DirUtil.h"
#include "roots.h"
#include "recovery_ui.h"
#include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
#include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
#include "extendedcommands.h"
#include "nandroid.h"
#include "mounts.h"
#include "flashutils/flashutils.h"
#include "edify/expr.h"
#include "mtdutils/mtdutils.h"
#include "mmcutils/mmcutils.h"
//#include "edify/parser.h"
Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
return NULL;
}
int size = 0;
int i;
for (i = 0; i < argc; ++i) {
size += strlen(args[i]);
}
char* buffer = malloc(size+1);
size = 0;
for (i = 0; i < argc; ++i) {
strcpy(buffer+size, args[i]);
size += strlen(args[i]);
free(args[i]);
}
free(args);
buffer[size] = '\0';
char* line = strtok(buffer, "\n");
while (line) {
ui_print("%s\n", line);
line = strtok(NULL, "\n");
}
return StringValue(buffer);
}
Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
return ErrorAbort(state, "%s() expects at least 1 arg", name);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
return NULL;
}
char** args2 = malloc(sizeof(char*) * (argc+1));
memcpy(args2, args, sizeof(char*) * argc);
args2[argc] = NULL;
fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc);
pid_t child = fork();
if (child == 0) {
execv(args2[0], args2);
fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno));
_exit(1);
}
int status;
waitpid(child, &status, 0);
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
fprintf(stderr, "run_program: child exited with status %d\n",
WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "run_program: child terminated by signal %d\n",
WTERMSIG(status));
}
int i;
for (i = 0; i < argc; ++i) {
free(args[i]);
}
free(args);
free(args2);
char buffer[20];
sprintf(buffer, "%d", status);
return StringValue(strdup(buffer));
}
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
return ErrorAbort(state, "%s() expects 1 arg, got %d", name, argc);
}
char *path;
if (ReadArgs(state, argv, 1, &path) < 0) {
return NULL;
}
ui_print("Formatting %s...\n", path);
if (0 != format_volume(path)) {
free(path);
return StringValue(strdup(""));
}
if (strcmp(path, "/data") == 0 && has_datadata()) {
ui_print("Formatting /datadata...\n", path);
if (0 != format_volume("/datadata")) {
free(path);
return StringValue(strdup(""));
}
if (0 != format_volume("/sdcard/.android_secure")) {
free(path);
return StringValue(strdup(""));
}
}
done:
return StringValue(strdup(path));
}
Value* BackupFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
}
char* path;
if (ReadArgs(state, argv, 1, &path) < 0) {
return NULL;
}
if (0 != nandroid_backup(path))
return StringValue(strdup(""));
return StringValue(strdup(path));
}
Value* RestoreFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc < 1) {
return ErrorAbort(state, "%s() expects at least 1 arg", name);
}
char** args = ReadVarArgs(state, argc, argv);
if (args == NULL) {
return NULL;
}
char** args2 = malloc(sizeof(char*) * (argc+1));
memcpy(args2, args, sizeof(char*) * argc);
args2[argc] = NULL;
char* path = strdup(args2[0]);
int restoreboot = 1;
int restoresystem = 1;
int restoredata = 1;
int restorecache = 1;
int restoresdext = 1;
int i;
for (i = 1; i < argc; i++)
{
if (args2[i] == NULL)
continue;
if (strcmp(args2[i], "noboot") == 0)
restoreboot = 0;
else if (strcmp(args2[i], "nosystem") == 0)
restoresystem = 0;
else if (strcmp(args2[i], "nodata") == 0)
restoredata = 0;
else if (strcmp(args2[i], "nocache") == 0)
restorecache = 0;
else if (strcmp(args2[i], "nosd-ext") == 0)
restoresdext = 0;
}
for (i = 0; i < argc; ++i) {
free(args[i]);
}
free(args);
free(args2);
if (0 != nandroid_restore(path, restoreboot, restoresystem, restoredata, restorecache, restoresdext, 0)) {
free(path);
return StringValue(strdup(""));
}
return StringValue(path);
}
Value* InstallZipFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
}
char* path;
if (ReadArgs(state, argv, 1, &path) < 0) {
return NULL;
}
if (0 != install_zip(path))
return StringValue(strdup(""));
return StringValue(strdup(path));
}
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL;
if (argc != 1) {
return ErrorAbort(state, "%s() expects 1 args, got %d", name, argc);
}
char* path;
if (ReadArgs(state, argv, 1, &path) < 0) {
return NULL;
}
if (0 != ensure_path_mounted(path))
return StringValue(strdup(""));
return StringValue(strdup(path));
}
void RegisterRecoveryHooks() {
RegisterFunction("mount", MountFn);
RegisterFunction("format", FormatFn);
RegisterFunction("ui_print", UIPrintFn);
RegisterFunction("run_program", RunProgramFn);
RegisterFunction("backup_rom", BackupFn);
RegisterFunction("restore_rom", RestoreFn);
RegisterFunction("install_zip", InstallZipFn);
}
static int hasInitializedEdify = 0;
int run_script_from_buffer(char* script_data, int script_len, char* filename)
{
if (!hasInitializedEdify) {
RegisterBuiltins();
RegisterRecoveryHooks();
FinishRegistration();
hasInitializedEdify = 1;
}
Expr* root;
int error_count = 0;
yy_scan_bytes(script_data, script_len);
int error = yyparse(&root, &error_count);
printf("parse returned %d; %d errors encountered\n", error, error_count);
if (error == 0 || error_count > 0) {
//ExprDump(0, root, buffer);
State state;
state.cookie = NULL;
state.script = script_data;
state.errmsg = NULL;
char* result = Evaluate(&state, root);
if (result == NULL) {
printf("result was NULL, message is: %s\n",
(state.errmsg == NULL ? "(NULL)" : state.errmsg));
free(state.errmsg);
return -1;
} else {
printf("result is [%s]\n", result);
}
}
return 0;
}