2009-06-10 23:11:53 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2016-10-11 00:48:37 +02:00
|
|
|
#include "updater/install.h"
|
|
|
|
|
2009-06-24 18:36:20 +02:00
|
|
|
#include <ctype.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <errno.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <ftw.h>
|
|
|
|
#include <inttypes.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <stdarg.h>
|
2009-06-24 18:36:20 +02:00
|
|
|
#include <stdio.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <sys/capability.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
2009-09-10 23:10:48 +02:00
|
|
|
#include <sys/wait.h>
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
#include <sys/xattr.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
2016-09-09 05:10:11 +02:00
|
|
|
#include <utime.h>
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-02-04 03:16:02 +01:00
|
|
|
#include <memory>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <string>
|
2016-02-04 03:16:02 +01:00
|
|
|
#include <vector>
|
|
|
|
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/file.h>
|
2016-11-23 01:29:50 +01:00
|
|
|
#include <android-base/logging.h>
|
2016-10-18 03:15:20 +02:00
|
|
|
#include <android-base/parsedouble.h>
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/parseint.h>
|
2016-09-24 00:30:55 +02:00
|
|
|
#include <android-base/properties.h>
|
2015-12-05 00:30:20 +01:00
|
|
|
#include <android-base/stringprintf.h>
|
2016-11-04 07:52:01 +01:00
|
|
|
#include <android-base/strings.h>
|
2016-10-11 00:48:37 +02:00
|
|
|
#include <cutils/android_reboot.h>
|
2016-10-06 08:17:01 +02:00
|
|
|
#include <ext4_utils/make_ext4fs.h>
|
|
|
|
#include <ext4_utils/wipe.h>
|
2016-02-08 20:15:50 +01:00
|
|
|
#include <openssl/sha.h>
|
2016-04-02 03:24:39 +02:00
|
|
|
#include <selinux/label.h>
|
|
|
|
#include <selinux/selinux.h>
|
2016-09-09 05:10:11 +02:00
|
|
|
#include <ziparchive/zip_archive.h>
|
2015-09-10 02:16:55 +02:00
|
|
|
|
2013-11-25 22:53:25 +01:00
|
|
|
#include "applypatch/applypatch.h"
|
2016-10-11 00:48:37 +02:00
|
|
|
#include "bootloader.h"
|
2009-06-10 23:11:53 +02:00
|
|
|
#include "edify/expr.h"
|
2016-04-30 20:49:59 +02:00
|
|
|
#include "error_code.h"
|
2016-06-10 02:41:22 +02:00
|
|
|
#include "mounts.h"
|
2015-12-16 01:04:53 +01:00
|
|
|
#include "ota_io.h"
|
2016-09-09 05:10:11 +02:00
|
|
|
#include "otautil/DirUtil.h"
|
|
|
|
#include "otautil/ZipUtil.h"
|
2016-02-08 20:15:50 +01:00
|
|
|
#include "print_sha1.h"
|
2014-11-21 09:12:28 +01:00
|
|
|
#include "tune2fs.h"
|
2016-10-11 00:48:37 +02:00
|
|
|
#include "updater/updater.h"
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2015-09-10 02:16:55 +02:00
|
|
|
// Send over the buffer to recovery though the command pipe.
|
|
|
|
static void uiPrint(State* state, const std::string& buffer) {
|
2016-11-23 01:29:50 +01:00
|
|
|
UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
|
|
|
|
|
|
|
|
// "line1\nline2\n" will be split into 3 tokens: "line1", "line2" and "".
|
|
|
|
// So skip sending empty strings to UI.
|
|
|
|
std::vector<std::string> lines = android::base::Split(buffer, "\n");
|
|
|
|
for (auto& line : lines) {
|
|
|
|
if (!line.empty()) {
|
|
|
|
fprintf(ui->cmd_pipe, "ui_print %s\n", line.c_str());
|
|
|
|
fprintf(ui->cmd_pipe, "ui_print\n");
|
2014-10-23 04:48:41 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2015-05-20 02:02:16 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
// On the updater side, we need to dump the contents to stderr (which has
|
|
|
|
// been redirected to the log file). Because the recovery will only print
|
|
|
|
// the contents to screen when processing pipe command ui_print.
|
|
|
|
LOG(INFO) << buffer;
|
2014-10-23 04:48:41 +02:00
|
|
|
}
|
|
|
|
|
2016-06-30 18:28:42 +02:00
|
|
|
void uiPrintf(State* _Nonnull state, const char* _Nonnull format, ...) {
|
2016-11-23 01:29:50 +01:00
|
|
|
std::string error_msg;
|
2015-09-10 02:16:55 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
|
|
android::base::StringAppendV(&error_msg, format, ap);
|
|
|
|
va_end(ap);
|
2015-09-10 02:16:55 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
uiPrint(state, error_msg);
|
2014-10-23 04:48:41 +02:00
|
|
|
}
|
|
|
|
|
2016-11-04 19:31:29 +01:00
|
|
|
static bool is_dir(const std::string& dirpath) {
|
|
|
|
struct stat st;
|
|
|
|
return stat(dirpath.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
|
|
|
|
}
|
|
|
|
|
2016-10-11 00:48:37 +02:00
|
|
|
// Create all parent directories of name, if necessary.
|
2016-11-04 19:31:29 +01:00
|
|
|
static bool make_parents(const std::string& name) {
|
2016-11-23 01:29:50 +01:00
|
|
|
size_t prev_end = 0;
|
|
|
|
while (prev_end < name.size()) {
|
|
|
|
size_t next_end = name.find('/', prev_end + 1);
|
|
|
|
if (next_end == std::string::npos) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
std::string dir_path = name.substr(0, next_end);
|
|
|
|
if (!is_dir(dir_path)) {
|
|
|
|
int result = mkdir(dir_path.c_str(), 0700);
|
|
|
|
if (result != 0) {
|
|
|
|
PLOG(ERROR) << "failed to mkdir " << dir_path << " when make parents for " << name;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG(INFO) << "created [" << dir_path << "]";
|
|
|
|
}
|
|
|
|
prev_end = next_end;
|
|
|
|
}
|
|
|
|
return true;
|
2016-10-11 00:48:37 +02:00
|
|
|
}
|
|
|
|
|
2010-07-01 18:18:44 +02:00
|
|
|
// mount(fs_type, partition_type, location, mount_point)
|
2016-11-04 07:25:04 +01:00
|
|
|
// mount(fs_type, partition_type, location, mount_point, mount_options)
|
2009-06-10 23:11:53 +02:00
|
|
|
//
|
2010-07-01 18:18:44 +02:00
|
|
|
// fs_type="ext4" partition_type="EMMC" location=device
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 4 && argc != 5) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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& fs_type = args[0];
|
|
|
|
const std::string& partition_type = args[1];
|
|
|
|
const std::string& location = args[2];
|
|
|
|
const std::string& mount_point = args[3];
|
|
|
|
std::string mount_options;
|
|
|
|
|
|
|
|
if (argc == 5) {
|
|
|
|
mount_options = args[4];
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (fs_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (partition_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
if (location.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
{
|
|
|
|
char* secontext = nullptr;
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (sehandle) {
|
|
|
|
selabel_lookup(sehandle, &secontext, mount_point.c_str(), 0755);
|
|
|
|
setfscreatecon(secontext);
|
|
|
|
}
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
mkdir(mount_point.c_str(), 0755);
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (secontext) {
|
|
|
|
freecon(secontext);
|
|
|
|
setfscreatecon(nullptr);
|
2012-02-09 20:13:23 +01:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (mount(location.c_str(), mount_point.c_str(), fs_type.c_str(),
|
|
|
|
MS_NOATIME | MS_NODEV | MS_NODIRATIME, mount_options.c_str()) < 0) {
|
|
|
|
uiPrintf(state, "%s: failed to mount %s at %s: %s\n", name, location.c_str(),
|
|
|
|
mount_point.c_str(), strerror(errno));
|
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2009-06-12 02:21:44 +02:00
|
|
|
|
|
|
|
// is_mounted(mount_point)
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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& mount_point = args[0];
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
|
|
|
"mount_point argument to unmount() can't be empty");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
scan_mounted_volumes();
|
|
|
|
MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
|
|
|
|
if (vol == nullptr) {
|
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, 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& mount_point = args[0];
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure,
|
|
|
|
"mount_point argument to unmount() can't be empty");
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
scan_mounted_volumes();
|
|
|
|
MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point.c_str());
|
|
|
|
if (vol == nullptr) {
|
|
|
|
uiPrintf(state, "unmount of %s failed; no such volume\n", mount_point.c_str());
|
|
|
|
return nullptr;
|
|
|
|
} else {
|
|
|
|
int ret = unmount_mounted_volume(vol);
|
|
|
|
if (ret != 0) {
|
|
|
|
uiPrintf(state, "unmount of %s failed (%d): %s\n", mount_point.c_str(), ret, strerror(errno));
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(mount_point);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2014-06-17 04:07:39 +02:00
|
|
|
static int exec_cmd(const char* path, char* const argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
pid_t child;
|
|
|
|
if ((child = vfork()) == 0) {
|
|
|
|
execv(path, argv);
|
|
|
|
_exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int status;
|
|
|
|
waitpid(child, &status, 0);
|
|
|
|
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
|
|
|
LOG(ERROR) << path << " failed with status " << WEXITSTATUS(status);
|
|
|
|
}
|
|
|
|
return WEXITSTATUS(status);
|
2014-06-17 04:07:39 +02:00
|
|
|
}
|
|
|
|
|
2012-02-09 20:13:23 +01:00
|
|
|
// format(fs_type, partition_type, location, fs_size, mount_point)
|
2009-06-10 23:11:53 +02:00
|
|
|
//
|
2016-11-23 01:29:50 +01:00
|
|
|
// fs_type="ext4" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
|
|
|
|
// fs_type="f2fs" partition_type="EMMC" location=device fs_size=<bytes> mount_point=<location>
|
2014-06-17 04:07:39 +02:00
|
|
|
// if fs_size == 0, then make fs uses the entire partition.
|
2011-01-15 03:55:05 +01:00
|
|
|
// if fs_size > 0, that is the size to use
|
2014-06-17 04:07:39 +02:00
|
|
|
// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 5) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
|
|
|
|
}
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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& fs_type = args[0];
|
|
|
|
const std::string& partition_type = args[1];
|
|
|
|
const std::string& location = args[2];
|
|
|
|
const std::string& fs_size = args[3];
|
|
|
|
const std::string& mount_point = args[4];
|
|
|
|
|
|
|
|
if (fs_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "fs_type argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (partition_type.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "partition_type argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
|
|
|
if (location.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "location argument to %s() can't be empty", name);
|
|
|
|
}
|
|
|
|
if (mount_point.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "mount_point argument to %s() can't be empty",
|
|
|
|
name);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
int64_t size;
|
|
|
|
if (!android::base::ParseInt(fs_size, &size)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s\n", name,
|
|
|
|
fs_size.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fs_type == "ext4") {
|
|
|
|
int status = make_ext4fs(location.c_str(), size, mount_point.c_str(), sehandle);
|
|
|
|
if (status != 0) {
|
|
|
|
LOG(ERROR) << name << ": make_ext4fs failed (" << status << ") on " << location;
|
|
|
|
return StringValue("");
|
2012-02-09 20:13:23 +01:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(location);
|
|
|
|
} else if (fs_type == "f2fs") {
|
|
|
|
if (size < 0) {
|
|
|
|
LOG(ERROR) << name << ": fs_size can't be negative for f2fs: " << fs_size;
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
std::string num_sectors = std::to_string(size / 512);
|
2012-02-09 20:13:23 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
const char* f2fs_path = "/sbin/mkfs.f2fs";
|
|
|
|
const char* const f2fs_argv[] = { "mkfs.f2fs", "-t", "-d1", location.c_str(),
|
|
|
|
num_sectors.c_str(), nullptr };
|
|
|
|
int status = exec_cmd(f2fs_path, const_cast<char* const*>(f2fs_argv));
|
|
|
|
if (status != 0) {
|
|
|
|
LOG(ERROR) << name << ": mkfs.f2fs failed (" << status << ") on " << location;
|
|
|
|
return StringValue("");
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(location);
|
|
|
|
} else {
|
|
|
|
LOG(ERROR) << name << ": unsupported fs_type \"" << fs_type << "\" partition_type \""
|
|
|
|
<< partition_type << "\"";
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return nullptr;
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2016-11-04 07:25:04 +01:00
|
|
|
// 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")
|
2013-11-07 02:42:20 +01:00
|
|
|
Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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];
|
2013-11-07 02:42:20 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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
|
2016-10-18 03:15:20 +02:00
|
|
|
return StringValue(dst_name);
|
2016-11-23 01:29:50 +01:00
|
|
|
} 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);
|
2013-11-07 02:42:20 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-04 07:25:04 +01:00
|
|
|
// 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.
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> paths(argc);
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
if (!Evaluate(state, argv[i], &paths[i])) {
|
|
|
|
return nullptr;
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
bool recursive = (strcmp(name, "delete_recursive") == 0);
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
int success = 0;
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) {
|
|
|
|
++success;
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(std::to_string(success));
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* ShowProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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& frac_str = args[0];
|
|
|
|
const std::string& sec_str = args[1];
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
double frac;
|
|
|
|
if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s\n", name,
|
|
|
|
frac_str.c_str());
|
|
|
|
}
|
|
|
|
int sec;
|
|
|
|
if (!android::base::ParseInt(sec_str.c_str(), &sec)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse int in %s\n", name,
|
|
|
|
sec_str.c_str());
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
|
|
|
|
fprintf(ui->cmd_pipe, "progress %f %d\n", frac, sec);
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(frac_str);
|
2009-06-24 18:36:20 +02:00
|
|
|
}
|
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* SetProgressFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& frac_str = args[0];
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
double frac;
|
|
|
|
if (!android::base::ParseDouble(frac_str.c_str(), &frac)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s: failed to parse double in %s\n", name,
|
|
|
|
frac_str.c_str());
|
|
|
|
}
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
|
|
|
|
fprintf(ui->cmd_pipe, "set_progress %f\n", frac);
|
2009-06-24 18:36:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(frac_str);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
// package_extract_dir(package_dir, dest_dir)
|
|
|
|
// Extracts all files from the package underneath package_dir and writes them to the
|
|
|
|
// corresponding tree beneath dest_dir. Any existing files are overwritten.
|
|
|
|
// Example: package_extract_dir("system", "/system")
|
|
|
|
//
|
|
|
|
// Note: package_dir needs to be a relative path; dest_dir needs to be an absolute path.
|
|
|
|
Value* PackageExtractDirFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& zip_path = args[0];
|
|
|
|
const std::string& dest_path = args[1];
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
// To create a consistent system image, never use the clock for timestamps.
|
|
|
|
constexpr struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
bool success = ExtractPackageRecursive(za, zip_path, dest_path, ×tamp, sehandle);
|
2016-09-09 05:10:11 +02:00
|
|
|
|
2016-11-18 07:49:56 +01:00
|
|
|
return StringValue(success ? "t" : "");
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
// package_extract_file(package_file[, dest_file])
|
|
|
|
// Extracts a single package_file from the update package and writes it to dest_file,
|
|
|
|
// overwriting existing files if necessary. Without the dest_file argument, returns the
|
|
|
|
// contents of the package file as a binary blob.
|
|
|
|
Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|
|
|
if (argc < 1 || argc > 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 or 2 args, got %d", name, argc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (argc == 2) {
|
|
|
|
// The two-argument version extracts to a file.
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
2016-11-15 06:29:52 +01:00
|
|
|
const std::string& zip_path = args[0];
|
|
|
|
const std::string& dest_path = args[1];
|
2010-02-01 23:40:12 +01:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
|
|
|
|
ZipString zip_string_path(zip_path.c_str());
|
|
|
|
ZipEntry entry;
|
|
|
|
if (FindEntry(za, zip_string_path, &entry) != 0) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << ": no " << zip_path << " in package";
|
2016-11-15 06:29:52 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
unique_fd fd(TEMP_FAILURE_RETRY(
|
|
|
|
ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
|
2016-11-15 06:29:52 +01:00
|
|
|
if (fd == -1) {
|
2016-11-23 01:29:50 +01:00
|
|
|
PLOG(ERROR) << name << ": can't open " << dest_path << " for write";
|
2016-11-15 06:29:52 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
bool success = true;
|
|
|
|
int32_t ret = ExtractEntryToFile(za, &entry, fd);
|
|
|
|
if (ret != 0) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << ": Failed to extract entry \"" << zip_path << "\" ("
|
|
|
|
<< entry.uncompressed_length << " bytes) to \"" << dest_path
|
|
|
|
<< "\": " << ErrorCodeString(ret);
|
2016-11-15 06:29:52 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
if (ota_fsync(fd) == -1) {
|
2016-11-23 01:29:50 +01:00
|
|
|
PLOG(ERROR) << "fsync of \"" << dest_path << "\" failed";
|
2016-11-15 06:29:52 +01:00
|
|
|
success = false;
|
|
|
|
}
|
|
|
|
if (ota_close(fd) == -1) {
|
2016-11-23 01:29:50 +01:00
|
|
|
PLOG(ERROR) << "close of \"" << dest_path << "\" failed";
|
2016-11-15 06:29:52 +01:00
|
|
|
success = false;
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
return StringValue(success ? "t" : "");
|
|
|
|
} else {
|
|
|
|
// The one-argument version returns the contents of the file as the result.
|
2016-02-04 03:16:02 +01:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse %d args", name, argc);
|
|
|
|
}
|
|
|
|
const std::string& zip_path = args[0];
|
2010-02-01 23:40:12 +01:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
ZipArchiveHandle za = static_cast<UpdaterInfo*>(state->cookie)->package_zip;
|
|
|
|
ZipString zip_string_path(zip_path.c_str());
|
|
|
|
ZipEntry entry;
|
|
|
|
if (FindEntry(za, zip_string_path, &entry) != 0) {
|
|
|
|
return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
|
|
|
|
zip_path.c_str());
|
|
|
|
}
|
2010-02-01 23:40:12 +01:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
std::string buffer;
|
|
|
|
buffer.resize(entry.uncompressed_length);
|
2010-02-01 23:40:12 +01:00
|
|
|
|
2016-11-15 06:29:52 +01:00
|
|
|
int32_t ret = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&buffer[0]), buffer.size());
|
|
|
|
if (ret != 0) {
|
|
|
|
return ErrorAbort(state, kPackageExtractFileFailure,
|
|
|
|
"%s: Failed to extract entry \"%s\" (%zu bytes) to memory: %s", name,
|
|
|
|
zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
|
2010-02-01 23:40:12 +01:00
|
|
|
}
|
2016-11-15 06:29:52 +01:00
|
|
|
|
|
|
|
return new Value(VAL_BLOB, buffer);
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2016-11-09 05:51:31 +01:00
|
|
|
// symlink(target, [src1, src2, ...])
|
|
|
|
// Creates all sources as symlinks to target. It unlinks any previously existing src1, src2, etc
|
|
|
|
// before creating symlinks.
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
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;
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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);
|
|
|
|
}
|
2009-06-10 23:11:53 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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;
|
2012-03-22 22:32:52 +01:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
|
|
|
if (bad != 0) {
|
|
|
|
return ErrorAbort(state, kSymlinkFailure, "%s: Failed to create %zu symlink(s)", name, bad);
|
|
|
|
}
|
|
|
|
return StringValue("t");
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|
|
|
|
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
struct perm_parsed_args {
|
2016-11-23 01:29:50 +01:00
|
|
|
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;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
};
|
|
|
|
|
2016-10-18 03:15:20 +02:00
|
|
|
static struct perm_parsed_args ParsePermArgs(State * state, int argc,
|
|
|
|
const std::vector<std::string>& args) {
|
2016-11-23 01:29:50 +01:00
|
|
|
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;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
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;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
static int ApplyParsedPerms(State* state, const char* filename, const struct stat* statptr,
|
|
|
|
struct perm_parsed_args parsed) {
|
|
|
|
int bad = 0;
|
unconditionally apply SELinux labels to symlinks
At the end of the OTA script, we walk through /system, updating
all the permissions on the filesystem, including the UID, GID,
standard UNIX permissions, capabilities, and SELinux labels.
In the case of a symbolic link, however, we want to skip most of
those operations. The UID, GID, UNIX permissions, and capabilities
don't meaningfully apply to symbolic links.
However, that's not true with SELinux labels. The SELinux label on
a symbolic link is important. We need to make sure the label on the
symbolic link is always updated, even if none of the other attributes
are updated.
This change unconditionally updates the SELinux label on the symbolic
link itself. lsetfilecon() is used, so that the link itself is updated,
not what it's pointing to.
In addition, drop the ENOTSUP special case. SELinux has been a
requirement since Android 4.4. Running without filesystem extended
attributes is no longer supported, and we shouldn't even try to handle
non-SELinux updates anymore. (Note: this could be problematic if
these scripts are ever used to produce OTA images for 4.2 devices)
Bug: 18079773
Change-Id: I87f99a1c88fe02bb2914f1884cac23ce1b385f91
2014-10-24 05:36:42 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
2013-09-11 00:34:19 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2013-09-11 00:34:19 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
/* 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++;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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++;
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return bad;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
2014-10-23 04:48:41 +02:00
|
|
|
static State* recursive_state;
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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);
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if ((argc % 2) != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects an odd number of arguments, got %d",
|
|
|
|
name, argc);
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argc, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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));
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
struct perm_parsed_args parsed = ParsePermArgs(state, argc, args);
|
|
|
|
int bad = 0;
|
|
|
|
bool recursive = (strcmp(name, "set_metadata_recursive") == 0);
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
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);
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (bad > 0) {
|
|
|
|
return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
|
|
|
|
}
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue("");
|
updater: introduce and set_metadata and set_metadata_recursive
Introduce two new updater functions:
* set_metadata
* set_metadata_recursive
Long term, these functions are intended to be more flexible replacements
for the following methods:
* set_perm
* set_perm_recursive
Usage:
set_metadata("filename", "key1", "value1", "key2", "value2", ...)
set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...)
Description:
set_metadata() and set_metadata_recursive() set the attributes on a file/directory
according to the key/value pairs provided. Today, the following keys are
supported:
* uid
* gid
* mode (set_perm_extd only)
* fmode (set_perm_extd_recursive only)
* dmode (set_perm_extd_recursive only)
* selabel
* capabilities
Unknown keys are logged as warnings, but are not fatal errors.
Examples:
* set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0");
This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0.
No other changes occur.
* set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750,
selinux label=u:object_r:system_file:s0, and clears the capabilities
associated with the file.
* set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0);
All files and directories under /system are set to uid=0, gid=0,
and selinux label=u:object_r:system_file:s0. Directories are set to
mode=0755. Files are set to mode=0644 and all capabilities are cleared.
Bug: 10183961
Bug: 10186213
Bug: 8985290
Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af
2013-09-07 23:41:06 +02:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
|
|
|
|
}
|
|
|
|
std::string key;
|
|
|
|
if (!Evaluate(state, argv[0], &key)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
std::string value = android::base::GetProperty(key, "");
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(value);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2009-06-18 19:11:50 +02:00
|
|
|
// file_getprop(file, key)
|
|
|
|
//
|
|
|
|
// interprets 'file' as a getprop-style file (key=value pairs, one
|
2016-11-03 22:49:01 +01:00
|
|
|
// per line. # comment lines, blank lines, lines without '=' ignored),
|
2014-04-26 03:47:18 +02:00
|
|
|
// and returns the value for 'key' (or "" if it isn't defined).
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-28 20:48:43 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2016-11-03 22:49:01 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& key = args[1];
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
struct stat st;
|
|
|
|
if (stat(filename.c_str(), &st) < 0) {
|
|
|
|
return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name,
|
|
|
|
filename.c_str(), strerror(errno));
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
constexpr off_t MAX_FILE_GETPROP_SIZE = 65536;
|
|
|
|
if (st.st_size > MAX_FILE_GETPROP_SIZE) {
|
|
|
|
return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)",
|
|
|
|
filename.c_str(), name, static_cast<long long>(MAX_FILE_GETPROP_SIZE));
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::string buffer(st.st_size, '\0');
|
|
|
|
unique_file f(ota_fopen(filename.c_str(), "rb"));
|
|
|
|
if (f == nullptr) {
|
|
|
|
return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename.c_str(),
|
|
|
|
strerror(errno));
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
if (ota_fread(&buffer[0], 1, st.st_size, f.get()) != static_cast<size_t>(st.st_size)) {
|
|
|
|
ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name,
|
|
|
|
static_cast<size_t>(st.st_size), filename.c_str());
|
|
|
|
return nullptr;
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
ota_fclose(f);
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> lines = android::base::Split(buffer, "\n");
|
|
|
|
for (size_t i = 0; i < lines.size(); i++) {
|
|
|
|
std::string line = android::base::Trim(lines[i]);
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// comment or blank line: skip to next line
|
|
|
|
if (line.empty() || line[0] == '#') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
size_t equal_pos = line.find('=');
|
|
|
|
if (equal_pos == std::string::npos) {
|
|
|
|
continue;
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// trim whitespace between key and '='
|
|
|
|
std::string str = android::base::Trim(line.substr(0, equal_pos));
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
// not the key we're looking for
|
|
|
|
if (key != str) continue;
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
|
|
|
|
}
|
2009-06-18 19:11:50 +02:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
return StringValue("");
|
2009-06-18 19:11:50 +02:00
|
|
|
}
|
|
|
|
|
2009-06-12 02:21:44 +02:00
|
|
|
// apply_patch_space(bytes)
|
2016-11-23 01:29:50 +01:00
|
|
|
Value* ApplyPatchSpaceFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& bytes_str = args[0];
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
size_t bytes;
|
|
|
|
if (!android::base::ParseUint(bytes_str.c_str(), &bytes)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count\n\n",
|
|
|
|
name, bytes_str.c_str());
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(CacheSizeCheck(bytes) ? "" : "t");
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
// apply_patch(src_file, tgt_file, tgt_sha1, tgt_size, patch1_sha1, patch1_blob, [...])
|
|
|
|
// Applies a binary patch to the src_file to produce the tgt_file. If the desired target is the
|
|
|
|
// same as the source, pass "-" for tgt_file. tgt_sha1 and tgt_size are the expected final SHA1
|
|
|
|
// hash and size of the target file. The remaining arguments must come in pairs: a SHA1 hash (a
|
|
|
|
// 40-character hex string) and a blob. The blob is the patch to be applied when the source
|
|
|
|
// file's current contents have the given SHA1.
|
|
|
|
//
|
|
|
|
// The patching is done in a safe manner that guarantees the target file either has the desired
|
|
|
|
// SHA1 hash and size, or it is untouched -- it will not be left in an unrecoverable intermediate
|
|
|
|
// state. If the process is interrupted during patching, the target file may be in an intermediate
|
|
|
|
// state; a copy exists in the cache partition so restarting the update can successfully update
|
|
|
|
// the file.
|
2010-02-22 23:46:32 +01:00
|
|
|
Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|
|
|
if (argc < 6 || (argc % 2) == 1) {
|
2016-04-30 20:49:59 +02:00
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 6 args and an "
|
2016-10-18 03:15:20 +02:00
|
|
|
"even number, got %d", name, argc);
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
|
|
|
|
2016-10-18 03:15:20 +02:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 4, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
const std::string& source_filename = args[0];
|
|
|
|
const std::string& target_filename = args[1];
|
|
|
|
const std::string& target_sha1 = args[2];
|
|
|
|
const std::string& target_size_str = args[3];
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2015-09-24 20:10:51 +02:00
|
|
|
size_t target_size;
|
2016-10-18 03:15:20 +02:00
|
|
|
if (!android::base::ParseUint(target_size_str.c_str(), &target_size)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): can't parse \"%s\" as byte count",
|
|
|
|
name, target_size_str.c_str());
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int patchcount = (argc-4) / 2;
|
2016-10-18 03:15:20 +02:00
|
|
|
std::vector<std::unique_ptr<Value>> arg_values;
|
|
|
|
if (!ReadValueArgs(state, argc-4, argv+4, &arg_values)) {
|
2016-02-04 03:16:02 +01:00
|
|
|
return nullptr;
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-02-04 03:16:02 +01:00
|
|
|
for (int i = 0; i < patchcount; ++i) {
|
2016-10-18 03:15:20 +02:00
|
|
|
if (arg_values[i * 2]->type != VAL_STRING) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name,
|
|
|
|
i * 2);
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
if (arg_values[i * 2 + 1]->type != VAL_BLOB) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name,
|
|
|
|
i * 2 + 1);
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-10-12 19:55:04 +02:00
|
|
|
std::vector<std::string> patch_sha_str;
|
2016-10-18 03:15:20 +02:00
|
|
|
std::vector<std::unique_ptr<Value>> patches;
|
2016-02-04 03:16:02 +01:00
|
|
|
for (int i = 0; i < patchcount; ++i) {
|
2016-10-18 03:15:20 +02:00
|
|
|
patch_sha_str.push_back(arg_values[i * 2]->data);
|
|
|
|
patches.push_back(std::move(arg_values[i * 2 + 1]));
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
2010-02-22 23:46:32 +01:00
|
|
|
|
2016-10-18 03:15:20 +02:00
|
|
|
int result = applypatch(source_filename.c_str(), target_filename.c_str(),
|
|
|
|
target_sha1.c_str(), target_size,
|
|
|
|
patch_sha_str, patches, nullptr);
|
2010-02-22 23:46:32 +01:00
|
|
|
|
2016-10-12 19:55:04 +02:00
|
|
|
return StringValue(result == 0 ? "t" : "");
|
2010-02-22 23:46:32 +01:00
|
|
|
}
|
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
// apply_patch_check(filename, [sha1, ...])
|
|
|
|
// Returns true if the contents of filename or the temporary copy in the cache partition (if
|
|
|
|
// present) have a SHA-1 checksum equal to one of the given sha1 values. sha1 values are
|
|
|
|
// specified as 40 hex digits. This function differs from sha1_check(read_file(filename),
|
|
|
|
// sha1 [, ...]) in that it knows to check the cache partition copy, so apply_patch_check() will
|
|
|
|
// succeed even if the file was corrupted by an interrupted apply_patch() update.
|
|
|
|
Value* ApplyPatchCheckFn(const char* name, State* state, int argc, Expr* argv[]) {
|
|
|
|
if (argc < 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): expected at least 1 arg, got %d", name,
|
|
|
|
argc);
|
|
|
|
}
|
2010-02-22 23:46:32 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
2010-02-22 23:46:32 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> sha1s;
|
|
|
|
if (!ReadArgs(state, argc - 1, argv + 1, &sha1s)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
int result = applypatch_check(filename.c_str(), sha1s);
|
2016-10-12 19:55:04 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(result == 0 ? "t" : "");
|
2009-06-12 02:21:44 +02:00
|
|
|
}
|
|
|
|
|
2015-09-10 02:16:55 +02:00
|
|
|
// This is the updater side handler for ui_print() in edify script. Contents
|
|
|
|
// will be sent over to the recovery side for on-screen display.
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argc, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
2009-06-12 21:24:39 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::string buffer = android::base::Join(args, "") + "\n";
|
|
|
|
uiPrint(state, buffer);
|
|
|
|
return StringValue(buffer);
|
2009-06-12 21:24:39 +02:00
|
|
|
}
|
|
|
|
|
2011-10-19 19:51:12 +02:00
|
|
|
Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 0) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
|
|
|
|
}
|
|
|
|
fprintf(static_cast<UpdaterInfo*>(state->cookie)->cmd_pipe, "wipe_cache\n");
|
|
|
|
return StringValue("t");
|
2011-10-19 19:51:12 +02:00
|
|
|
}
|
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc < 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argc, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
2009-09-10 23:10:48 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
char* args2[argc + 1];
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
|
|
args2[i] = &args[i][0];
|
|
|
|
}
|
|
|
|
args2[argc] = nullptr;
|
2009-09-10 23:10:48 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(INFO) << "about to run program [" << args2[0] << "] with " << argc << " args";
|
2009-09-10 23:10:48 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
pid_t child = fork();
|
|
|
|
if (child == 0) {
|
|
|
|
execv(args2[0], args2);
|
|
|
|
PLOG(ERROR) << "run_program: execv failed";
|
|
|
|
_exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int status;
|
|
|
|
waitpid(child, &status, 0);
|
|
|
|
if (WIFEXITED(status)) {
|
|
|
|
if (WEXITSTATUS(status) != 0) {
|
|
|
|
LOG(ERROR) << "run_program: child exited with status " << WEXITSTATUS(status);
|
2009-09-10 23:10:48 +02:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
} else if (WIFSIGNALED(status)) {
|
|
|
|
LOG(ERROR) << "run_program: child terminated by signal " << WTERMSIG(status);
|
|
|
|
}
|
2009-09-10 23:10:48 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
return StringValue(std::to_string(status));
|
2009-09-10 23:10:48 +02:00
|
|
|
}
|
|
|
|
|
2010-02-18 01:11:44 +01:00
|
|
|
// sha1_check(data)
|
|
|
|
// to return the sha1 of the data (given in the format returned by
|
|
|
|
// read_file).
|
|
|
|
//
|
|
|
|
// sha1_check(data, sha1_hex, [sha1_hex, ...])
|
|
|
|
// returns the sha1 of the file if it matches any of the hex
|
|
|
|
// strings passed, or "" if it does not equal any of them.
|
|
|
|
//
|
|
|
|
Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc < 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
|
|
|
|
}
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::unique_ptr<Value>> args;
|
|
|
|
if (!ReadValueArgs(state, argc, argv, &args)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (args[0]->type == VAL_INVALID) {
|
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
uint8_t digest[SHA_DIGEST_LENGTH];
|
|
|
|
SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest);
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc == 1) {
|
|
|
|
return StringValue(print_sha1(digest));
|
|
|
|
}
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
uint8_t arg_digest[SHA_DIGEST_LENGTH];
|
|
|
|
if (args[i]->type != VAL_STRING) {
|
|
|
|
LOG(ERROR) << name << "(): arg " << i << " is not a string; skipping";
|
|
|
|
} else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) {
|
|
|
|
// Warn about bad args and skip them.
|
|
|
|
LOG(ERROR) << name << "(): error parsing \"" << args[i]->data << "\" as sha-1; skipping";
|
|
|
|
} else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
|
|
|
|
// Found a match.
|
|
|
|
return args[i].release();
|
2010-02-18 01:11:44 +01:00
|
|
|
}
|
2016-11-23 01:29:50 +01:00
|
|
|
}
|
2016-02-08 20:15:50 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
// Didn't match any of the hex strings; return false.
|
|
|
|
return StringValue("");
|
2010-02-18 01:11:44 +01:00
|
|
|
}
|
|
|
|
|
2010-08-02 19:29:49 +02:00
|
|
|
// Read a local file and return its contents (the Value* returned
|
2010-02-18 01:11:44 +01:00
|
|
|
// is actually a FileContents*).
|
|
|
|
Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
Value* v = new Value(VAL_INVALID, "");
|
2010-02-18 01:11:44 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
FileContents fc;
|
|
|
|
if (LoadFileContents(filename.c_str(), &fc) == 0) {
|
|
|
|
v->type = VAL_BLOB;
|
|
|
|
v->data = std::string(fc.data.begin(), fc.data.end());
|
|
|
|
}
|
|
|
|
return v;
|
2010-02-18 01:11:44 +01:00
|
|
|
}
|
2009-06-12 02:21:44 +02:00
|
|
|
|
2016-11-04 07:52:01 +01:00
|
|
|
// write_value(value, filename)
|
|
|
|
// Writes 'value' to 'filename'.
|
|
|
|
// Example: write_value("960000", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq")
|
|
|
|
Value* WriteValueFn(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, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& filename = args[1];
|
|
|
|
if (filename.empty()) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Filename cannot be empty", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string& value = args[0];
|
|
|
|
if (!android::base::WriteStringToFile(value, filename)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
PLOG(ERROR) << name << ": Failed to write to \"" << filename << "\"";
|
2016-11-04 07:52:01 +01:00
|
|
|
return StringValue("");
|
|
|
|
} else {
|
|
|
|
return StringValue("t");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-25 22:53:25 +01:00
|
|
|
// Immediately reboot the device. Recovery is not finished normally,
|
|
|
|
// so if you reboot into recovery it will re-start applying the
|
|
|
|
// current package (because nothing has cleared the copy of the
|
|
|
|
// arguments stored in the BCB).
|
|
|
|
//
|
|
|
|
// The argument is the partition name passed to the android reboot
|
|
|
|
// property. It can be "recovery" to boot from the recovery
|
|
|
|
// partition, or "" (empty string) to boot from the regular boot
|
|
|
|
// partition.
|
|
|
|
Value* RebootNowFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-18 21:01:26 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& property = args[1];
|
|
|
|
|
|
|
|
// Zero out the 'command' field of the bootloader message. Leave the rest intact.
|
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
memset(boot.command, 0, sizeof(boot.command));
|
|
|
|
if (!write_bootloader_message_to(boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
const std::string reboot_cmd = "reboot," + property;
|
|
|
|
android::base::SetProperty(ANDROID_RB_PROPERTY, reboot_cmd);
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
sleep(5);
|
|
|
|
return ErrorAbort(state, kRebootFailure, "%s() failed to reboot", name);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Store a string value somewhere that future invocations of recovery
|
|
|
|
// can access it. This value is called the "stage" and can be used to
|
|
|
|
// drive packages that need to do reboots in the middle of
|
|
|
|
// installation and keep track of where they are in the multi-stage
|
|
|
|
// install.
|
|
|
|
//
|
|
|
|
// The first argument is the block device for the misc partition
|
|
|
|
// ("/misc" in the fstab), which is where this value is stored. The
|
|
|
|
// second argument is the string to store; it should not exceed 31
|
|
|
|
// bytes.
|
|
|
|
Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-18 21:01:26 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& stagestr = args[1];
|
|
|
|
|
|
|
|
// Store this value in the misc partition, immediately after the
|
|
|
|
// bootloader message that the main recovery uses to save its
|
|
|
|
// arguments in case of the device restarting midway through
|
|
|
|
// package installation.
|
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
|
|
|
strlcpy(boot.stage, stagestr.c_str(), sizeof(boot.stage));
|
|
|
|
if (!write_bootloader_message_to(boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to write to \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue(filename);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return the value most recently saved with SetStageFn. The argument
|
|
|
|
// is the block device for the misc partition.
|
|
|
|
Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-18 21:01:26 +01:00
|
|
|
if (argc != 1) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 1, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
bootloader_message boot;
|
|
|
|
std::string err;
|
|
|
|
if (!read_bootloader_message_from(&boot, filename, &err)) {
|
2016-11-23 01:29:50 +01:00
|
|
|
LOG(ERROR) << name << "(): Failed to read from \"" << filename << "\": " << err;
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue("");
|
|
|
|
}
|
2013-11-25 22:53:25 +01:00
|
|
|
|
2016-11-18 21:01:26 +01:00
|
|
|
return StringValue(boot.stage);
|
2013-11-25 22:53:25 +01:00
|
|
|
}
|
|
|
|
|
2014-02-25 01:02:50 +01:00
|
|
|
Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-28 20:48:43 +01:00
|
|
|
if (argc != 2) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
|
|
|
|
}
|
2014-02-25 01:02:50 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, 2, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
|
|
|
|
}
|
|
|
|
const std::string& filename = args[0];
|
|
|
|
const std::string& len_str = args[1];
|
2014-02-25 01:02:50 +01:00
|
|
|
|
2016-11-28 20:48:43 +01:00
|
|
|
size_t len;
|
|
|
|
if (!android::base::ParseUint(len_str.c_str(), &len)) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
unique_fd fd(ota_open(filename.c_str(), O_WRONLY, 0644));
|
|
|
|
// The wipe_block_device function in ext4_utils returns 0 on success and 1
|
|
|
|
// for failure.
|
|
|
|
int status = wipe_block_device(fd, len);
|
|
|
|
return StringValue((status == 0) ? "t" : "");
|
2014-02-25 01:02:50 +01:00
|
|
|
}
|
|
|
|
|
2014-05-23 17:40:35 +02:00
|
|
|
Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc != 0) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
|
|
|
|
}
|
|
|
|
UpdaterInfo* ui = static_cast<UpdaterInfo*>(state->cookie);
|
|
|
|
fprintf(ui->cmd_pipe, "enable_reboot\n");
|
|
|
|
return StringValue("t");
|
2014-05-23 17:40:35 +02:00
|
|
|
}
|
|
|
|
|
2014-11-21 09:12:28 +01:00
|
|
|
Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
|
2016-11-23 01:29:50 +01:00
|
|
|
if (argc == 0) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() expects args, got %d", name, argc);
|
|
|
|
}
|
2014-11-21 09:12:28 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
std::vector<std::string> args;
|
|
|
|
if (!ReadArgs(state, argc, argv, &args)) {
|
|
|
|
return ErrorAbort(state, kArgsParsingFailure, "%s() could not read args", name);
|
|
|
|
}
|
2014-11-21 09:12:28 +01:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
char* args2[argc + 1];
|
|
|
|
// Tune2fs expects the program name as its args[0]
|
|
|
|
args2[0] = const_cast<char*>(name);
|
|
|
|
if (args2[0] == nullptr) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < argc; ++i) {
|
|
|
|
args2[i + 1] = &args[i][0];
|
|
|
|
}
|
2016-10-18 03:15:20 +02:00
|
|
|
|
2016-11-23 01:29:50 +01:00
|
|
|
// tune2fs changes the file system parameters on an ext2 file system; it
|
|
|
|
// returns 0 on success.
|
|
|
|
int result = tune2fs_main(argc + 1, args2);
|
|
|
|
if (result != 0) {
|
|
|
|
return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", name, result);
|
|
|
|
}
|
|
|
|
return StringValue("t");
|
2014-11-21 09:12:28 +01:00
|
|
|
}
|
|
|
|
|
2009-06-10 23:11:53 +02:00
|
|
|
void RegisterInstallFunctions() {
|
2016-11-23 01:29:50 +01:00
|
|
|
RegisterFunction("mount", MountFn);
|
|
|
|
RegisterFunction("is_mounted", IsMountedFn);
|
|
|
|
RegisterFunction("unmount", UnmountFn);
|
|
|
|
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);
|
|
|
|
|
|
|
|
RegisterFunction("apply_patch", ApplyPatchFn);
|
|
|
|
RegisterFunction("apply_patch_check", ApplyPatchCheckFn);
|
|
|
|
RegisterFunction("apply_patch_space", ApplyPatchSpaceFn);
|
|
|
|
|
|
|
|
RegisterFunction("wipe_block_device", WipeBlockDeviceFn);
|
|
|
|
|
|
|
|
RegisterFunction("read_file", ReadFileFn);
|
|
|
|
RegisterFunction("sha1_check", Sha1CheckFn);
|
|
|
|
RegisterFunction("rename", RenameFn);
|
|
|
|
RegisterFunction("write_value", WriteValueFn);
|
|
|
|
|
|
|
|
RegisterFunction("wipe_cache", WipeCacheFn);
|
|
|
|
|
|
|
|
RegisterFunction("ui_print", UIPrintFn);
|
|
|
|
|
|
|
|
RegisterFunction("run_program", RunProgramFn);
|
|
|
|
|
|
|
|
RegisterFunction("reboot_now", RebootNowFn);
|
|
|
|
RegisterFunction("get_stage", GetStageFn);
|
|
|
|
RegisterFunction("set_stage", SetStageFn);
|
|
|
|
|
|
|
|
RegisterFunction("enable_reboot", EnableRebootFn);
|
|
|
|
RegisterFunction("tune2fs", Tune2FsFn);
|
2009-06-10 23:11:53 +02:00
|
|
|
}
|