diff options
-rw-r--r-- | tests/component/updater_test.cpp | 113 | ||||
-rw-r--r-- | updater/install.cpp | 362 |
2 files changed, 0 insertions, 475 deletions
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp index fa5f03134..8c4bdbaa4 100644 --- a/tests/component/updater_test.cpp +++ b/tests/component/updater_test.cpp @@ -161,119 +161,6 @@ TEST_F(UpdaterTest, file_getprop) { expect("", script6.c_str(), kNoCause); } -TEST_F(UpdaterTest, delete) { - // Delete none. - expect("0", "delete()", kNoCause); - expect("0", "delete(\"/doesntexist\")", kNoCause); - expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\")", kNoCause); - expect("0", "delete(\"/doesntexist1\", \"/doesntexist2\", \"/doesntexist3\")", kNoCause); - - // Delete one file. - TemporaryFile temp_file1; - ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path)); - std::string script1("delete(\"" + std::string(temp_file1.path) + "\")"); - expect("1", script1.c_str(), kNoCause); - - // Delete two files. - TemporaryFile temp_file2; - ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file2.path)); - TemporaryFile temp_file3; - ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file3.path)); - std::string script2("delete(\"" + std::string(temp_file2.path) + "\", \"" + - std::string(temp_file3.path) + "\")"); - expect("2", script2.c_str(), kNoCause); - - // Delete already deleted files. - expect("0", script2.c_str(), kNoCause); - - // Delete one out of three. - TemporaryFile temp_file4; - ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file4.path)); - std::string script3("delete(\"/doesntexist1\", \"" + std::string(temp_file4.path) + - "\", \"/doesntexist2\")"); - expect("1", script3.c_str(), kNoCause); -} - -TEST_F(UpdaterTest, rename) { - // rename() expects two arguments. - expect(nullptr, "rename()", kArgsParsingFailure); - expect(nullptr, "rename(\"arg1\")", kArgsParsingFailure); - expect(nullptr, "rename(\"arg1\", \"arg2\", \"arg3\")", kArgsParsingFailure); - - // src_name or dst_name cannot be empty. - expect(nullptr, "rename(\"\", \"arg2\")", kArgsParsingFailure); - expect(nullptr, "rename(\"arg1\", \"\")", kArgsParsingFailure); - - // File doesn't exist (both of src and dst). - expect(nullptr, "rename(\"/doesntexist\", \"/doesntexisteither\")" , kFileRenameFailure); - - // Can't create parent directory. - TemporaryFile temp_file1; - ASSERT_TRUE(android::base::WriteStringToFile("abc", temp_file1.path)); - std::string script1("rename(\"" + std::string(temp_file1.path) + "\", \"/proc/0/file1\")"); - expect(nullptr, script1.c_str(), kFileRenameFailure); - - // Rename. - TemporaryFile temp_file2; - std::string script2("rename(\"" + std::string(temp_file1.path) + "\", \"" + - std::string(temp_file2.path) + "\")"); - expect(temp_file2.path, script2.c_str(), kNoCause); - - // Already renamed. - expect(temp_file2.path, script2.c_str(), kNoCause); - - // Parents create successfully. - TemporaryFile temp_file3; - TemporaryDir td; - std::string temp_dir(td.path); - std::string dst_file = temp_dir + "/aaa/bbb/a.txt"; - std::string script3("rename(\"" + std::string(temp_file3.path) + "\", \"" + dst_file + "\")"); - expect(dst_file.c_str(), script3.c_str(), kNoCause); - - // Clean up the temp files under td. - ASSERT_EQ(0, unlink(dst_file.c_str())); - ASSERT_EQ(0, rmdir((temp_dir + "/aaa/bbb").c_str())); - ASSERT_EQ(0, rmdir((temp_dir + "/aaa").c_str())); -} - -TEST_F(UpdaterTest, symlink) { - // symlink expects 1+ argument. - expect(nullptr, "symlink()", kArgsParsingFailure); - - // symlink should fail if src is an empty string. - TemporaryFile temp_file1; - std::string script1("symlink(\"" + std::string(temp_file1.path) + "\", \"\")"); - expect(nullptr, script1.c_str(), kSymlinkFailure); - - std::string script2("symlink(\"" + std::string(temp_file1.path) + "\", \"src1\", \"\")"); - expect(nullptr, script2.c_str(), kSymlinkFailure); - - // symlink failed to remove old src. - std::string script3("symlink(\"" + std::string(temp_file1.path) + "\", \"/proc\")"); - expect(nullptr, script3.c_str(), kSymlinkFailure); - - // symlink can create symlinks. - TemporaryFile temp_file; - std::string content = "magicvalue"; - ASSERT_TRUE(android::base::WriteStringToFile(content, temp_file.path)); - - TemporaryDir td; - std::string src1 = std::string(td.path) + "/symlink1"; - std::string src2 = std::string(td.path) + "/symlink2"; - std::string script4("symlink(\"" + std::string(temp_file.path) + "\", \"" + - src1 + "\", \"" + src2 + "\")"); - expect("t", script4.c_str(), kNoCause); - - // Verify the created symlinks. - struct stat sb; - ASSERT_TRUE(lstat(src1.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode)); - ASSERT_TRUE(lstat(src2.c_str(), &sb) == 0 && S_ISLNK(sb.st_mode)); - - // Clean up the leftovers. - ASSERT_EQ(0, unlink(src1.c_str())); - ASSERT_EQ(0, unlink(src2.c_str())); -} - TEST_F(UpdaterTest, package_extract_dir) { // package_extract_dir expects 2 arguments. expect(nullptr, "package_extract_dir()", kArgsParsingFailure); diff --git a/updater/install.cpp b/updater/install.cpp index c7ecdb5c7..0963333fc 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -332,68 +332,6 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { return nullptr; } -// rename(src_name, dst_name) -// Renames src_name to dst_name. It automatically creates the necessary directories for dst_name. -// Example: rename("system/app/Hangouts/Hangouts.apk", "system/priv-app/Hangouts/Hangouts.apk") -Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc != 2) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); - } - - std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - const std::string& src_name = args[0]; - const std::string& dst_name = args[1]; - - if (src_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "src_name argument to %s() can't be empty", name); - } - if (dst_name.empty()) { - return ErrorAbort(state, kArgsParsingFailure, "dst_name argument to %s() can't be empty", name); - } - if (!make_parents(dst_name)) { - return ErrorAbort(state, kFileRenameFailure, "Creating parent of %s failed, error %s", - dst_name.c_str(), strerror(errno)); - } else if (access(dst_name.c_str(), F_OK) == 0 && access(src_name.c_str(), F_OK) != 0) { - // File was already moved - return StringValue(dst_name); - } else if (rename(src_name.c_str(), dst_name.c_str()) != 0) { - return ErrorAbort(state, kFileRenameFailure, "Rename of %s to %s failed, error %s", - src_name.c_str(), dst_name.c_str(), strerror(errno)); - } - - return StringValue(dst_name); -} - -// delete([filename, ...]) -// Deletes all the filenames listed. Returns the number of files successfully deleted. -// -// delete_recursive([dirname, ...]) -// Recursively deletes dirnames and all their contents. Returns the number of directories -// successfully deleted. -Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { - std::vector<std::string> paths(argc); - for (int i = 0; i < argc; ++i) { - if (!Evaluate(state, argv[i], &paths[i])) { - return nullptr; - } - } - - bool recursive = (strcmp(name, "delete_recursive") == 0); - - int success = 0; - for (int i = 0; i < argc; ++i) { - if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) { - ++success; - } - } - - return StringValue(std::to_string(success)); -} - - Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 2) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); @@ -557,288 +495,6 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv } } -// symlink(target, [src1, src2, ...]) -// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc -// before creating symlinks. -Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { - if (argc == 0) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); - } - std::string target; - if (!Evaluate(state, argv[0], &target)) { - return nullptr; - } - - std::vector<std::string> srcs; - if (!ReadArgs(state, argc - 1, argv + 1, &srcs)) { - return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name); - } - - size_t bad = 0; - for (const auto& src : srcs) { - if (unlink(src.c_str()) == -1 && errno != ENOENT) { - PLOG(ERROR) << name << ": failed to remove " << src; - ++bad; - } else if (!make_parents(src)) { - LOG(ERROR) << name << ": failed to symlink " << src << " to " << target - << ": making parents failed"; - ++bad; - } else if (symlink(target.c_str(), src.c_str()) == -1) { - PLOG(ERROR) << name << ": failed to symlink " << src << " to " << target; - ++bad; - } - } - if (bad != 0) { - return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad); - } - return StringValue("t"); -} - -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; - const char* selabel; - bool has_capabilities; - uint64_t capabilities; -}; - -static struct perm_parsed_args ParsePermArgs(State * state, int argc, - const std::vector<std::string>& args) { - struct perm_parsed_args parsed; - int bad = 0; - static int max_warnings = 20; - - memset(&parsed, 0, sizeof(parsed)); - - for (int i = 1; i < argc; i += 2) { - if (args[i] == "uid") { - int64_t uid; - if (sscanf(args[i + 1].c_str(), "%" SCNd64, &uid) == 1) { - parsed.uid = uid; - parsed.has_uid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid UID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "gid") { - int64_t gid; - if (sscanf(args[i + 1].c_str(), "%" SCNd64, &gid) == 1) { - parsed.gid = gid; - parsed.has_gid = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid GID \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "mode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.mode = mode; - parsed.has_mode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid mode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "dmode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.dmode = mode; - parsed.has_dmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "fmode") { - int32_t mode; - if (sscanf(args[i + 1].c_str(), "%" SCNi32, &mode) == 1) { - parsed.fmode = mode; - parsed.has_fmode = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "capabilities") { - int64_t capabilities; - if (sscanf(args[i + 1].c_str(), "%" SCNi64, &capabilities) == 1) { - parsed.capabilities = capabilities; - parsed.has_capabilities = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (args[i] == "selabel") { - if (!args[i + 1].empty()) { - parsed.selabel = args[i + 1].c_str(); - parsed.has_selabel = true; - } else { - uiPrintf(state, "ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1].c_str()); - bad++; - } - continue; - } - if (max_warnings != 0) { - printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i].c_str()); - max_warnings--; - if (max_warnings == 0) { - LOG(INFO) << "ParsedPermArgs: suppressing further warnings"; - } - } - } - return parsed; -} - -static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr, - struct perm_parsed_args parsed) { - int bad = 0; - - if (parsed.has_selabel) { - if (lsetfilecon(filename, parsed.selabel) != 0) { - uiPrintf(state, "ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", filename, - parsed.selabel, strerror(errno)); - bad++; - } - } - - /* ignore symlinks */ - if (S_ISLNK(statptr->st_mode)) { - return bad; - } - - if (parsed.has_uid) { - if (chown(filename, parsed.uid, -1) < 0) { - uiPrintf(state, "ApplyParsedPerms: chown of %s to %d failed: %s\n", filename, parsed.uid, - strerror(errno)); - bad++; - } - } - - if (parsed.has_gid) { - if (chown(filename, -1, parsed.gid) < 0) { - uiPrintf(state, "ApplyParsedPerms: chgrp of %s to %d failed: %s\n", filename, parsed.gid, - strerror(errno)); - bad++; - } - } - - if (parsed.has_mode) { - if (chmod(filename, parsed.mode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.mode, - strerror(errno)); - bad++; - } - } - - if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { - if (chmod(filename, parsed.dmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.dmode, - strerror(errno)); - bad++; - } - } - - if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { - if (chmod(filename, parsed.fmode) < 0) { - uiPrintf(state, "ApplyParsedPerms: chmod of %s to %d failed: %s\n", filename, parsed.fmode, - 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) - uiPrintf(state, "ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", filename, - parsed.capabilities, 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) { - uiPrintf(state, "ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", filename, - parsed.capabilities, strerror(errno)); - bad++; - } - } - } - - 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 State* recursive_state; - -static int do_SetMetadataRecursive(const char* filename, const struct stat* statptr, int fileflags, - struct FTW* pfwt) { - return ApplyParsedPerms(recursive_state, filename, statptr, recursive_parsed_args); -} - -static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { - if ((argc % 2) != 1) { - return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %d", - name, argc); - } - - std::vector<std::string> args; - if (!ReadArgs(state, argc, argv, &args)) { - return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name); - } - - struct stat sb; - if (lstat(args[0].c_str(), &sb) == -1) { - return ErrorAbort(state, kSetMetadataFailure, "%s: Error on lstat of \"%s\": %s", name, - args[0].c_str(), strerror(errno)); - } - - struct perm_parsed_args parsed = ParsePermArgs(state, argc, args); - int bad = 0; - bool recursive = (strcmp(name, "set_metadata_recursive") == 0); - - if (recursive) { - recursive_parsed_args = parsed; - recursive_state = state; - bad += nftw(args[0].c_str(), do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); - memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); - recursive_state = NULL; - } else { - bad += ApplyParsedPerms(state, args[0].c_str(), &sb, parsed); - } - - if (bad > 0) { - return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); - } - - return StringValue(""); -} - Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 1) { return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); @@ -1356,25 +1012,8 @@ void RegisterInstallFunctions() { RegisterFunction("format", FormatFn); RegisterFunction("show_progress", ShowProgressFn); RegisterFunction("set_progress", SetProgressFn); - RegisterFunction("delete", DeleteFn); - RegisterFunction("delete_recursive", DeleteFn); RegisterFunction("package_extract_dir", PackageExtractDirFn); RegisterFunction("package_extract_file", PackageExtractFileFn); - RegisterFunction("symlink", SymlinkFn); - - // 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); @@ -1387,7 +1026,6 @@ void RegisterInstallFunctions() { RegisterFunction("read_file", ReadFileFn); RegisterFunction("sha1_check", Sha1CheckFn); - RegisterFunction("rename", RenameFn); RegisterFunction("write_value", WriteValueFn); RegisterFunction("wipe_cache", WipeCacheFn); |