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; | ||||
| } | ||||
|  | ||||
| // 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. | ||||
| 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 | ||||
|   | ||||
| @@ -32,17 +32,6 @@ | ||||
| #include "mtdutils/mtdutils.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) | ||||
| // | ||||
| @@ -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, | ||||
|                                int data_len, void* ctx) { | ||||
|     int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len); | ||||
| @@ -670,6 +758,7 @@ void RegisterInstallFunctions() { | ||||
|     RegisterFunction("set_perm_recursive", SetPermFn); | ||||
|  | ||||
|     RegisterFunction("getprop", GetPropFn); | ||||
|     RegisterFunction("file_getprop", FileGetPropFn); | ||||
|     RegisterFunction("write_raw_image", WriteRawImageFn); | ||||
|     RegisterFunction("write_firmware_image", WriteFirmwareImageFn); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user