summaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
Diffstat (limited to 'updater')
-rw-r--r--updater/Android.mk2
-rw-r--r--updater/install.c411
-rw-r--r--updater/updater.c24
3 files changed, 332 insertions, 105 deletions
diff --git a/updater/Android.mk b/updater/Android.mk
index 4271371e9..67e98ecd4 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -31,7 +31,7 @@ LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_UPDATER_LIBS) $(TARGET_RECOVERY_UPDA
LOCAL_STATIC_LIBRARIES += libapplypatch libedify libmtdutils libminzip libz
LOCAL_STATIC_LIBRARIES += libmincrypt libbz
LOCAL_STATIC_LIBRARIES += libminelf
-LOCAL_STATIC_LIBRARIES += libcutils libstdc++ libc
+LOCAL_STATIC_LIBRARIES += libcutils liblog libstdc++ libc
LOCAL_STATIC_LIBRARIES += libselinux
LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
diff --git a/updater/install.c b/updater/install.c
index 19054236c..1455557ca 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -27,6 +27,12 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
+#include <selinux/selinux.h>
+#include <ftw.h>
+#include <sys/capability.h>
+#include <sys/xattr.h>
+#include <linux/xattr.h>
+#include <inttypes.h>
#include "cutils/misc.h"
#include "cutils/properties.h"
@@ -97,13 +103,13 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
const MtdPartition* mtd;
mtd = mtd_find_partition_by_name(location);
if (mtd == NULL) {
- fprintf(stderr, "%s: no mtd partition named \"%s\"",
+ printf("%s: no mtd partition named \"%s\"",
name, location);
result = strdup("");
goto done;
}
if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) {
- fprintf(stderr, "mtd mount of %s failed: %s\n",
+ printf("mtd mount of %s failed: %s\n",
location, strerror(errno));
result = strdup("");
goto done;
@@ -112,7 +118,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
} else {
if (mount(location, mount_point, fs_type,
MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) {
- fprintf(stderr, "%s: failed to mount %s at %s: %s\n",
+ printf("%s: failed to mount %s at %s: %s\n",
name, location, mount_point, strerror(errno));
result = strdup("");
} else {
@@ -175,7 +181,7 @@ Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
scan_mounted_volumes();
const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point);
if (vol == NULL) {
- fprintf(stderr, "unmount of %s failed; no such volume\n", mount_point);
+ printf("unmount of %s failed; no such volume\n", mount_point);
result = strdup("");
} else {
unmount_mounted_volume(vol);
@@ -233,25 +239,25 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
mtd_scan_partitions();
const MtdPartition* mtd = mtd_find_partition_by_name(location);
if (mtd == NULL) {
- fprintf(stderr, "%s: no mtd partition named \"%s\"",
+ printf("%s: no mtd partition named \"%s\"",
name, location);
result = strdup("");
goto done;
}
MtdWriteContext* ctx = mtd_write_partition(mtd);
if (ctx == NULL) {
- fprintf(stderr, "%s: can't write \"%s\"", name, location);
+ printf("%s: can't write \"%s\"", name, location);
result = strdup("");
goto done;
}
if (mtd_erase_blocks(ctx, -1) == -1) {
mtd_write_close(ctx);
- fprintf(stderr, "%s: failed to erase \"%s\"", name, location);
+ printf("%s: failed to erase \"%s\"", name, location);
result = strdup("");
goto done;
}
if (mtd_write_close(ctx) != 0) {
- fprintf(stderr, "%s: failed to close \"%s\"", name, location);
+ printf("%s: failed to close \"%s\"", name, location);
result = strdup("");
goto done;
}
@@ -260,7 +266,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
} else if (strcmp(fs_type, "ext4") == 0) {
int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle);
if (status != 0) {
- fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
+ printf("%s: make_ext4fs failed (%d) on %s",
name, status, location);
result = strdup("");
goto done;
@@ -268,7 +274,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
result = location;
#endif
} else {
- fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"",
+ printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"",
name, fs_type, partition_type);
}
@@ -279,6 +285,40 @@ done:
return StringValue(result);
}
+Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
+ char* result = NULL;
+ if (argc != 2) {
+ return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
+ }
+
+ char* src_name;
+ char* dst_name;
+
+ if (ReadArgs(state, argv, 2, &src_name, &dst_name) < 0) {
+ return NULL;
+ }
+ if (strlen(src_name) == 0) {
+ ErrorAbort(state, "src_name argument to %s() can't be empty", name);
+ goto done;
+ }
+ if (strlen(dst_name) == 0) {
+ ErrorAbort(state, "dst_name argument to %s() can't be empty",
+ name);
+ goto done;
+ }
+
+ if (rename(src_name, dst_name) != 0) {
+ ErrorAbort(state, "Rename of %s() to %s() failed, error %s()",
+ src_name, dst_name, strerror(errno));
+ } else {
+ result = dst_name;
+ }
+
+done:
+ free(src_name);
+ if (result != dst_name) free(dst_name);
+ return StringValue(result);
+}
Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
char** paths = malloc(argc * sizeof(char*));
@@ -394,13 +434,13 @@ Value* PackageExtractFileFn(const char* name, State* state,
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path);
if (entry == NULL) {
- fprintf(stderr, "%s: no %s in package\n", name, zip_path);
+ printf("%s: no %s in package\n", name, zip_path);
goto done2;
}
FILE* f = fopen(dest_path, "wb");
if (f == NULL) {
- fprintf(stderr, "%s: can't open %s for write: %s\n",
+ printf("%s: can't open %s for write: %s\n",
name, dest_path, strerror(errno));
goto done2;
}
@@ -426,14 +466,14 @@ Value* PackageExtractFileFn(const char* name, State* state,
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path);
if (entry == NULL) {
- fprintf(stderr, "%s: no %s in package\n", name, zip_path);
+ printf("%s: no %s in package\n", name, zip_path);
goto done1;
}
v->size = mzGetZipEntryUncompLen(entry);
v->data = malloc(v->size);
if (v->data == NULL) {
- fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n",
+ printf("%s: failed to allocate %ld bytes for %s\n",
name, (long)v->size, zip_path);
goto done1;
}
@@ -460,13 +500,13 @@ static int make_parents(char* name) {
*p = '\0';
if (make_parents(name) < 0) return -1;
int result = mkdir(name, 0700);
- if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name);
+ if (result == 0) printf("symlink(): created [%s]\n", name);
*p = '/';
if (result == 0 || errno == EEXIST) {
// successfully created or already existed; we're done
return 0;
} else {
- fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno));
+ printf("failed to mkdir %s: %s\n", name, strerror(errno));
return -1;
}
}
@@ -494,18 +534,18 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
for (i = 0; i < argc-1; ++i) {
if (unlink(srcs[i]) < 0) {
if (errno != ENOENT) {
- fprintf(stderr, "%s: failed to remove %s: %s\n",
+ printf("%s: failed to remove %s: %s\n",
name, srcs[i], strerror(errno));
++bad;
}
}
if (make_parents(srcs[i])) {
- fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n",
+ printf("%s: failed to symlink %s to %s: making parents failed\n",
name, srcs[i], target);
++bad;
}
if (symlink(target, srcs[i]) < 0) {
- fprintf(stderr, "%s: failed to symlink %s to %s: %s\n",
+ printf("%s: failed to symlink %s to %s: %s\n",
name, srcs[i], target, strerror(errno));
++bad;
}
@@ -518,74 +558,247 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(strdup(""));
}
-
-Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) {
- char* result = NULL;
- bool recursive = (strcmp(name, "set_perm_recursive") == 0);
-
- int min_args = 4 + (recursive ? 1 : 0);
- if (argc < min_args) {
- return ErrorAbort(state, "%s() expects %d+ args, got %d",
- name, min_args, argc);
+struct perm_parsed_args {
+ bool has_uid;
+ uid_t uid;
+ bool has_gid;
+ gid_t gid;
+ bool has_mode;
+ mode_t mode;
+ bool has_fmode;
+ mode_t fmode;
+ bool has_dmode;
+ mode_t dmode;
+ bool has_selabel;
+ char* selabel;
+ bool has_capabilities;
+ uint64_t capabilities;
+};
+
+static struct perm_parsed_args ParsePermArgs(int argc, char** args) {
+ int i;
+ struct perm_parsed_args parsed;
+ int bad = 0;
+ static int max_warnings = 20;
+
+ memset(&parsed, 0, sizeof(parsed));
+
+ for (i = 1; i < argc; i += 2) {
+ if (strcmp("uid", args[i]) == 0) {
+ int64_t uid;
+ if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) {
+ parsed.uid = uid;
+ parsed.has_uid = true;
+ } else {
+ printf("ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("gid", args[i]) == 0) {
+ int64_t gid;
+ if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) {
+ parsed.gid = gid;
+ parsed.has_gid = true;
+ } else {
+ printf("ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("mode", args[i]) == 0) {
+ int32_t mode;
+ if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
+ parsed.mode = mode;
+ parsed.has_mode = true;
+ } else {
+ printf("ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("dmode", args[i]) == 0) {
+ int32_t mode;
+ if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
+ parsed.dmode = mode;
+ parsed.has_dmode = true;
+ } else {
+ printf("ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("fmode", args[i]) == 0) {
+ int32_t mode;
+ if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) {
+ parsed.fmode = mode;
+ parsed.has_fmode = true;
+ } else {
+ printf("ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("capabilities", args[i]) == 0) {
+ int64_t capabilities;
+ if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) {
+ parsed.capabilities = capabilities;
+ parsed.has_capabilities = true;
+ } else {
+ printf("ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (strcmp("selabel", args[i]) == 0) {
+ if (args[i+1][0] != '\0') {
+ parsed.selabel = args[i+1];
+ parsed.has_selabel = true;
+ } else {
+ printf("ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]);
+ bad++;
+ }
+ continue;
+ }
+ if (max_warnings != 0) {
+ printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]);
+ max_warnings--;
+ if (max_warnings == 0) {
+ printf("ParsedPermArgs: suppressing further warnings\n");
+ }
+ }
}
+ return parsed;
+}
- char** args = ReadVarArgs(state, argc, argv);
- if (args == NULL) return NULL;
-
- char* end;
- int i;
+static int ApplyParsedPerms(
+ const char* filename,
+ const struct stat *statptr,
+ struct perm_parsed_args parsed)
+{
int bad = 0;
- int uid = strtoul(args[0], &end, 0);
- if (*end != '\0' || args[0][0] == 0) {
- ErrorAbort(state, "%s: \"%s\" not a valid uid", name, args[0]);
- goto done;
+ /* ignore symlinks */
+ if (S_ISLNK(statptr->st_mode)) {
+ return 0;
}
- int gid = strtoul(args[1], &end, 0);
- if (*end != '\0' || args[1][0] == 0) {
- ErrorAbort(state, "%s: \"%s\" not a valid gid", name, args[1]);
- goto done;
+ if (parsed.has_uid) {
+ if (chown(filename, parsed.uid, -1) < 0) {
+ printf("ApplyParsedPerms: chown of %s to %d failed: %s\n",
+ filename, parsed.uid, strerror(errno));
+ bad++;
+ }
}
- if (recursive) {
- int dir_mode = strtoul(args[2], &end, 0);
- if (*end != '\0' || args[2][0] == 0) {
- ErrorAbort(state, "%s: \"%s\" not a valid dirmode", name, args[2]);
- goto done;
+ if (parsed.has_gid) {
+ if (chown(filename, -1, parsed.gid) < 0) {
+ printf("ApplyParsedPerms: chgrp of %s to %d failed: %s\n",
+ filename, parsed.gid, strerror(errno));
+ bad++;
}
+ }
- int file_mode = strtoul(args[3], &end, 0);
- if (*end != '\0' || args[3][0] == 0) {
- ErrorAbort(state, "%s: \"%s\" not a valid filemode",
- name, args[3]);
- goto done;
+ if (parsed.has_mode) {
+ if (chmod(filename, parsed.mode) < 0) {
+ printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
+ filename, parsed.mode, strerror(errno));
+ bad++;
}
+ }
- for (i = 4; i < argc; ++i) {
- dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode);
+ if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) {
+ if (chmod(filename, parsed.dmode) < 0) {
+ printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
+ filename, parsed.dmode, strerror(errno));
+ bad++;
}
- } else {
- int mode = strtoul(args[2], &end, 0);
- if (*end != '\0' || args[2][0] == 0) {
- ErrorAbort(state, "%s: \"%s\" not a valid mode", name, args[2]);
- goto done;
+ }
+
+ if (parsed.has_fmode && S_ISREG(statptr->st_mode)) {
+ if (chmod(filename, parsed.fmode) < 0) {
+ printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n",
+ filename, parsed.fmode, strerror(errno));
+ bad++;
}
+ }
- for (i = 3; i < argc; ++i) {
- if (chown(args[i], uid, gid) < 0) {
- fprintf(stderr, "%s: chown of %s to %d %d failed: %s\n",
- name, args[i], uid, gid, strerror(errno));
- ++bad;
+ if (parsed.has_selabel) {
+ // TODO: Don't silently ignore ENOTSUP
+ if (lsetfilecon(filename, parsed.selabel) && (errno != ENOTSUP)) {
+ printf("ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n",
+ filename, parsed.selabel, strerror(errno));
+ bad++;
+ }
+ }
+
+ if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) {
+ if (parsed.capabilities == 0) {
+ if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) {
+ // Report failure unless it's ENODATA (attribute not set)
+ printf("ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n",
+ filename, parsed.capabilities, strerror(errno));
+ bad++;
}
- if (chmod(args[i], mode) < 0) {
- fprintf(stderr, "%s: chmod of %s to %o failed: %s\n",
- name, args[i], mode, strerror(errno));
- ++bad;
+ } else {
+ struct vfs_cap_data cap_data;
+ memset(&cap_data, 0, sizeof(cap_data));
+ cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
+ cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff);
+ cap_data.data[0].inheritable = 0;
+ cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32);
+ cap_data.data[1].inheritable = 0;
+ if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) {
+ printf("ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n",
+ filename, parsed.capabilities, strerror(errno));
+ bad++;
}
}
}
- result = strdup("");
+
+ return bad;
+}
+
+// nftw doesn't allow us to pass along context, so we need to use
+// global variables. *sigh*
+static struct perm_parsed_args recursive_parsed_args;
+
+static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr,
+ int fileflags, struct FTW *pfwt) {
+ return ApplyParsedPerms(filename, statptr, recursive_parsed_args);
+}
+
+static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) {
+ int i;
+ int bad = 0;
+ static int nwarnings = 0;
+ struct stat sb;
+ Value* result = NULL;
+
+ bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
+
+ if ((argc % 2) != 1) {
+ return ErrorAbort(state, "%s() expects an odd number of arguments, got %d",
+ name, argc);
+ }
+
+ char** args = ReadVarArgs(state, argc, argv);
+ if (args == NULL) return NULL;
+
+ if (lstat(args[0], &sb) == -1) {
+ result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno));
+ goto done;
+ }
+
+ struct perm_parsed_args parsed = ParsePermArgs(argc, args);
+
+ if (recursive) {
+ recursive_parsed_args = parsed;
+ bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS);
+ memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args));
+ } else {
+ bad += ApplyParsedPerms(args[0], &sb, parsed);
+ }
done:
for (i = 0; i < argc; ++i) {
@@ -593,13 +806,16 @@ done:
}
free(args);
- if (bad) {
- free(result);
+ if (result != NULL) {
+ return result;
+ }
+
+ if (bad > 0) {
return ErrorAbort(state, "%s: some changes failed", name);
}
- return StringValue(result);
-}
+ return StringValue(strdup(""));
+}
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) {
@@ -648,7 +864,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
buffer = malloc(st.st_size+1);
if (buffer == NULL) {
- ErrorAbort(state, "%s: failed to alloc %lld bytes", name, st.st_size+1);
+ ErrorAbort(state, "%s: failed to alloc %lld bytes", name, (long long)st.st_size+1);
goto done;
}
@@ -661,7 +877,7 @@ Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (fread(buffer, 1, st.st_size, f) != st.st_size) {
ErrorAbort(state, "%s: failed to read %lld bytes from %s",
- name, st.st_size+1, filename);
+ name, (long long)st.st_size+1, filename);
fclose(f);
goto done;
}
@@ -720,7 +936,7 @@ 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);
if (r == data_len) return true;
- fprintf(stderr, "%s\n", strerror(errno));
+ printf("%s\n", strerror(errno));
return false;
}
@@ -752,14 +968,14 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
mtd_scan_partitions();
const MtdPartition* mtd = mtd_find_partition_by_name(partition);
if (mtd == NULL) {
- fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition);
+ printf("%s: no mtd partition named \"%s\"\n", name, partition);
result = strdup("");
goto done;
}
MtdWriteContext* ctx = mtd_write_partition(mtd);
if (ctx == NULL) {
- fprintf(stderr, "%s: can't write mtd partition \"%s\"\n",
+ printf("%s: can't write mtd partition \"%s\"\n",
name, partition);
result = strdup("");
goto done;
@@ -772,7 +988,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
char* filename = contents->data;
FILE* f = fopen(filename, "rb");
if (f == NULL) {
- fprintf(stderr, "%s: can't open %s: %s\n",
+ printf("%s: can't open %s: %s\n",
name, filename, strerror(errno));
result = strdup("");
goto done;
@@ -793,15 +1009,15 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
success = (wrote == contents->size);
}
if (!success) {
- fprintf(stderr, "mtd_write_data to %s failed: %s\n",
+ printf("mtd_write_data to %s failed: %s\n",
partition, strerror(errno));
}
if (mtd_erase_blocks(ctx, -1) == -1) {
- fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
+ printf("%s: error erasing blocks of %s\n", name, partition);
}
if (mtd_write_close(ctx) != 0) {
- fprintf(stderr, "%s: error closing write of %s\n", name, partition);
+ printf("%s: error closing write of %s\n", name, partition);
}
printf("%s %s partition\n",
@@ -988,23 +1204,23 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
memcpy(args2, args, sizeof(char*) * argc);
args2[argc] = NULL;
- fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc);
+ printf("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));
+ printf("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",
+ printf("run_program: child exited with status %d\n",
WEXITSTATUS(status));
}
} else if (WIFSIGNALED(status)) {
- fprintf(stderr, "run_program: child terminated by signal %d\n",
+ printf("run_program: child terminated by signal %d\n",
WTERMSIG(status));
}
@@ -1053,11 +1269,11 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
}
if (args[0]->size < 0) {
- fprintf(stderr, "%s(): no file contents received", name);
+ printf("%s(): no file contents received", name);
return StringValue(strdup(""));
}
uint8_t digest[SHA_DIGEST_SIZE];
- SHA(args[0]->data, args[0]->size, digest);
+ SHA_hash(args[0]->data, args[0]->size, digest);
FreeValue(args[0]);
if (argc == 1) {
@@ -1068,12 +1284,12 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE);
for (i = 1; i < argc; ++i) {
if (args[i]->type != VAL_STRING) {
- fprintf(stderr, "%s(): arg %d is not a string; skipping",
+ printf("%s(): arg %d is not a string; skipping",
name, i);
} else if (ParseSha1(args[i]->data, arg_digest) != 0) {
// Warn about bad args and skip them.
- fprintf(stderr, "%s(): error parsing \"%s\" as sha-1; skipping",
- name, args[i]->data);
+ printf("%s(): error parsing \"%s\" as sha-1; skipping",
+ name, args[i]->data);
} else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) {
break;
}
@@ -1133,8 +1349,18 @@ void RegisterInstallFunctions() {
RegisterFunction("package_extract_dir", PackageExtractDirFn);
RegisterFunction("package_extract_file", PackageExtractFileFn);
RegisterFunction("symlink", SymlinkFn);
- RegisterFunction("set_perm", SetPermFn);
- RegisterFunction("set_perm_recursive", SetPermFn);
+
+ // Usage:
+ // set_metadata("filename", "key1", "value1", "key2", "value2", ...)
+ // Example:
+ // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
+ RegisterFunction("set_metadata", SetMetadataFn);
+
+ // Usage:
+ // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
+ // Example:
+ // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
+ RegisterFunction("set_metadata_recursive", SetMetadataFn);
RegisterFunction("getprop", GetPropFn);
RegisterFunction("file_getprop", FileGetPropFn);
@@ -1146,6 +1372,7 @@ void RegisterInstallFunctions() {
RegisterFunction("read_file", ReadFileFn);
RegisterFunction("sha1_check", Sha1CheckFn);
+ RegisterFunction("rename", RenameFn);
RegisterFunction("wipe_cache", WipeCacheFn);
diff --git a/updater/updater.c b/updater/updater.c
index 58ac27f9e..c7009feac 100644
--- a/updater/updater.c
+++ b/updater/updater.c
@@ -36,13 +36,14 @@ struct selabel_handle *sehandle;
int main(int argc, char** argv) {
// Various things log information to stdout or stderr more or less
- // at random. The log file makes more sense if buffering is
- // turned off so things appear in the right order.
+ // at random (though we've tried to standardize on stdout). The
+ // log file makes more sense if buffering is turned off so things
+ // appear in the right order.
setbuf(stdout, NULL);
setbuf(stderr, NULL);
if (argc != 4) {
- fprintf(stderr, "unexpected number of arguments (%d)\n", argc);
+ printf("unexpected number of arguments (%d)\n", argc);
return 1;
}
@@ -50,7 +51,7 @@ int main(int argc, char** argv) {
if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||
version[1] != '\0') {
// We support version 1, 2, or 3.
- fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "
+ printf("wrong updater binary API; expected 1, 2, or 3; "
"got %s\n",
argv[1]);
return 2;
@@ -69,20 +70,20 @@ int main(int argc, char** argv) {
int err;
err = mzOpenZipArchive(package_data, &za);
if (err != 0) {
- fprintf(stderr, "failed to open package %s: %s\n",
+ printf("failed to open package %s: %s\n",
package_data, strerror(err));
return 3;
}
const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);
if (script_entry == NULL) {
- fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data);
+ printf("failed to find %s in %s\n", SCRIPT_NAME, package_data);
return 4;
}
char* script = malloc(script_entry->uncompLen+1);
if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {
- fprintf(stderr, "failed to read script from package\n");
+ printf("failed to read script from package\n");
return 5;
}
script[script_entry->uncompLen] = '\0';
@@ -101,7 +102,7 @@ int main(int argc, char** argv) {
yy_scan_string(script);
int error = yyparse(&root, &error_count);
if (error != 0 || error_count > 0) {
- fprintf(stderr, "%d parse errors\n", error_count);
+ printf("%d parse errors\n", error_count);
return 6;
}
@@ -112,7 +113,6 @@ int main(int argc, char** argv) {
sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
if (!sehandle) {
- fprintf(stderr, "Warning: No file_contexts\n");
fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
}
@@ -131,10 +131,10 @@ int main(int argc, char** argv) {
char* result = Evaluate(&state, root);
if (result == NULL) {
if (state.errmsg == NULL) {
- fprintf(stderr, "script aborted (no error message)\n");
+ printf("script aborted (no error message)\n");
fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
} else {
- fprintf(stderr, "script aborted: %s\n", state.errmsg);
+ printf("script aborted: %s\n", state.errmsg);
char* line = strtok(state.errmsg, "\n");
while (line) {
fprintf(cmd_pipe, "ui_print %s\n", line);
@@ -145,7 +145,7 @@ int main(int argc, char** argv) {
free(state.errmsg);
return 7;
} else {
- fprintf(stderr, "script result was [%s]\n", result);
+ fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result);
free(result);
}