add file_getprop() to updater
Add a function to read a property from a ".prop"-formatted file (key=value pairs, one per line, ignore # comment lines and blank lines). Move ErrorAbort to the core of edify; it's not specific to updater now that errors aren't stored in the app cookie.
This commit is contained in:
13
edify/expr.c
13
edify/expr.c
@@ -417,3 +417,16 @@ char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
|
|||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use printf-style arguments to compose an error message to put into
|
||||||
|
// *state. Returns NULL.
|
||||||
|
char* ErrorAbort(State* state, char* format, ...) {
|
||||||
|
char* buffer = malloc(4096);
|
||||||
|
va_list v;
|
||||||
|
va_start(v, format);
|
||||||
|
vsnprintf(buffer, 4096, format, v);
|
||||||
|
va_end(v);
|
||||||
|
free(state->errmsg);
|
||||||
|
state->errmsg = buffer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -118,5 +118,9 @@ int ReadArgs(State* state, Expr* argv[], int count, ...);
|
|||||||
// strings it contains.
|
// strings it contains.
|
||||||
char** ReadVarArgs(State* state, int argc, Expr* argv[]);
|
char** ReadVarArgs(State* state, int argc, Expr* argv[]);
|
||||||
|
|
||||||
|
// Use printf-style arguments to compose an error message to put into
|
||||||
|
// *state. Returns NULL.
|
||||||
|
char* ErrorAbort(State* state, char* format, ...);
|
||||||
|
|
||||||
|
|
||||||
#endif // _EXPRESSION_H
|
#endif // _EXPRESSION_H
|
||||||
|
|||||||
@@ -32,17 +32,6 @@
|
|||||||
#include "mtdutils/mtdutils.h"
|
#include "mtdutils/mtdutils.h"
|
||||||
#include "updater.h"
|
#include "updater.h"
|
||||||
|
|
||||||
char* ErrorAbort(State* state, char* format, ...) {
|
|
||||||
char* buffer = malloc(4096);
|
|
||||||
va_list v;
|
|
||||||
va_start(v, format);
|
|
||||||
vsnprintf(buffer, 4096, format, v);
|
|
||||||
va_end(v);
|
|
||||||
free(state->errmsg);
|
|
||||||
state->errmsg = buffer;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// mount(type, location, mount_point)
|
// mount(type, location, mount_point)
|
||||||
//
|
//
|
||||||
@@ -449,6 +438,105 @@ char* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// file_getprop(file, key)
|
||||||
|
//
|
||||||
|
// interprets 'file' as a getprop-style file (key=value pairs, one
|
||||||
|
// per line, # comment lines and blank lines okay), and returns the value
|
||||||
|
// for 'key' (or "" if it isn't defined).
|
||||||
|
char* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
|
||||||
|
char* result = NULL;
|
||||||
|
char* buffer = NULL;
|
||||||
|
char* filename;
|
||||||
|
char* key;
|
||||||
|
if (ReadArgs(state, argv, 2, &filename, &key) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (stat(filename, &st) < 0) {
|
||||||
|
ErrorAbort(state, "%s: failed to stat \"%s\": %s",
|
||||||
|
name, filename, strerror(errno));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_FILE_GETPROP_SIZE 65536
|
||||||
|
|
||||||
|
if (st.st_size > MAX_FILE_GETPROP_SIZE) {
|
||||||
|
ErrorAbort(state, "%s too large for %s (max %d)",
|
||||||
|
filename, name, MAX_FILE_GETPROP_SIZE);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = malloc(st.st_size+1);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
ErrorAbort(state, "%s: failed to alloc %d bytes", name, st.st_size+1);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* f = fopen(filename, "rb");
|
||||||
|
if (f == NULL) {
|
||||||
|
ErrorAbort(state, "%s: failed to open %s: %s",
|
||||||
|
name, filename, strerror(errno));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread(buffer, 1, st.st_size, f) != st.st_size) {
|
||||||
|
ErrorAbort(state, "%s: failed to read %d bytes from %s",
|
||||||
|
name, st.st_size+1, filename);
|
||||||
|
fclose(f);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
buffer[st.st_size] = '\0';
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
char* line = strtok(buffer, "\n");
|
||||||
|
do {
|
||||||
|
// skip whitespace at start of line
|
||||||
|
while (*line && isspace(*line)) ++line;
|
||||||
|
|
||||||
|
// comment or blank line: skip to next line
|
||||||
|
if (*line == '\0' || *line == '#') continue;
|
||||||
|
|
||||||
|
char* equal = strchr(line, '=');
|
||||||
|
if (equal == NULL) {
|
||||||
|
ErrorAbort(state, "%s: malformed line \"%s\": %s not a prop file?",
|
||||||
|
name, line, filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim whitespace between key and '='
|
||||||
|
char* key_end = equal-1;
|
||||||
|
while (key_end > line && isspace(*key_end)) --key_end;
|
||||||
|
key_end[1] = '\0';
|
||||||
|
|
||||||
|
// not the key we're looking for
|
||||||
|
if (strcmp(key, line) != 0) continue;
|
||||||
|
|
||||||
|
// skip whitespace after the '=' to the start of the value
|
||||||
|
char* val_start = equal+1;
|
||||||
|
while(*val_start && isspace(*val_start)) ++val_start;
|
||||||
|
|
||||||
|
// trim trailing whitespace
|
||||||
|
char* val_end = val_start + strlen(val_start)-1;
|
||||||
|
while (val_end > val_start && isspace(*val_end)) --val_end;
|
||||||
|
val_end[1] = '\0';
|
||||||
|
|
||||||
|
result = strdup(val_start);
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while ((line = strtok(NULL, "\n")));
|
||||||
|
|
||||||
|
if (result == NULL) result = strdup("");
|
||||||
|
|
||||||
|
done:
|
||||||
|
free(filename);
|
||||||
|
free(key);
|
||||||
|
free(buffer);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool write_raw_image_cb(const unsigned char* data,
|
static bool write_raw_image_cb(const unsigned char* data,
|
||||||
int data_len, void* ctx) {
|
int data_len, void* ctx) {
|
||||||
int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len);
|
int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len);
|
||||||
@@ -670,6 +758,7 @@ void RegisterInstallFunctions() {
|
|||||||
RegisterFunction("set_perm_recursive", SetPermFn);
|
RegisterFunction("set_perm_recursive", SetPermFn);
|
||||||
|
|
||||||
RegisterFunction("getprop", GetPropFn);
|
RegisterFunction("getprop", GetPropFn);
|
||||||
|
RegisterFunction("file_getprop", FileGetPropFn);
|
||||||
RegisterFunction("write_raw_image", WriteRawImageFn);
|
RegisterFunction("write_raw_image", WriteRawImageFn);
|
||||||
RegisterFunction("write_firmware_image", WriteFirmwareImageFn);
|
RegisterFunction("write_firmware_image", WriteFirmwareImageFn);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user