Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef52ae14 authored by Tom Cherry's avatar Tom Cherry Committed by Wei Wang
Browse files

init: Use std::string for write_file()

The content parameter of write_file() previously took a char* that was
then converted to a std::string in WriteStringToFd().  One unfortunate
effect of this, is that it is impossible to write data that contains
'\0' within it, as the new string will only contain characters up
until the '\0'.

This changes write_file() to take an std::string, such that
std::string::size() is used to determine the length of the string,
allowing it to contain null characters.

Also change the path parameter of read_file() and write_file() for
consistency.

Lastly, add a test for handling strings with '\0' in them.

Bug: 36726045
Bug: 36576280
Test: Boot bullhead, run unit tests
Change-Id: Idad60e4228ee2de741ab3ab6a4917065b5e63cd8
(cherry picked from commit 53089aa2)
parent 79af3c6d
Loading
Loading
Loading
Loading
+3 −5
Original line number Original line Diff line number Diff line
@@ -155,7 +155,7 @@ static int do_class_restart(const std::vector<std::string>& args) {
}
}


static int do_domainname(const std::vector<std::string>& args) {
static int do_domainname(const std::vector<std::string>& args) {
    return write_file("/proc/sys/kernel/domainname", args[1].c_str()) ? 0 : 1;
    return write_file("/proc/sys/kernel/domainname", args[1]) ? 0 : 1;
}
}


static int do_enable(const std::vector<std::string>& args) {
static int do_enable(const std::vector<std::string>& args) {
@@ -179,7 +179,7 @@ static int do_export(const std::vector<std::string>& args) {
}
}


static int do_hostname(const std::vector<std::string>& args) {
static int do_hostname(const std::vector<std::string>& args) {
    return write_file("/proc/sys/kernel/hostname", args[1].c_str()) ? 0 : 1;
    return write_file("/proc/sys/kernel/hostname", args[1]) ? 0 : 1;
}
}


static int do_ifup(const std::vector<std::string>& args) {
static int do_ifup(const std::vector<std::string>& args) {
@@ -648,9 +648,7 @@ static int do_verity_update_state(const std::vector<std::string>& args) {
}
}


static int do_write(const std::vector<std::string>& args) {
static int do_write(const std::vector<std::string>& args) {
    const char* path = args[1].c_str();
    return write_file(args[1], args[2]) ? 0 : 1;
    const char* value = args[2].c_str();
    return write_file(path, value) ? 0 : 1;
}
}


static int do_copy(const std::vector<std::string>& args) {
static int do_copy(const std::vector<std::string>& args) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -96,7 +96,7 @@ bool Parser::ParseConfigFile(const std::string& path) {
    LOG(INFO) << "Parsing file " << path << "...";
    LOG(INFO) << "Parsing file " << path << "...";
    Timer t;
    Timer t;
    std::string data;
    std::string data;
    if (!read_file(path.c_str(), &data)) {
    if (!read_file(path, &data)) {
        return false;
        return false;
    }
    }


+5 −4
Original line number Original line Diff line number Diff line
@@ -161,10 +161,11 @@ out_unlink:
    return -1;
    return -1;
}
}


bool read_file(const char* path, std::string* content) {
bool read_file(const std::string& path, std::string* content) {
    content->clear();
    content->clear();


    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
    android::base::unique_fd fd(
        TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
    if (fd == -1) {
    if (fd == -1) {
        return false;
        return false;
    }
    }
@@ -184,9 +185,9 @@ bool read_file(const char* path, std::string* content) {
    return android::base::ReadFdToString(fd, content);
    return android::base::ReadFdToString(fd, content);
}
}


bool write_file(const char* path, const char* content) {
bool write_file(const std::string& path, const std::string& content) {
    android::base::unique_fd fd(
    android::base::unique_fd fd(
        TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600)));
        TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0600)));
    if (fd == -1) {
    if (fd == -1) {
        PLOG(ERROR) << "write_file: Unable to open '" << path << "'";
        PLOG(ERROR) << "write_file: Unable to open '" << path << "'";
        return false;
        return false;
+2 −2
Original line number Original line Diff line number Diff line
@@ -32,8 +32,8 @@ using namespace std::chrono_literals;
int create_socket(const char *name, int type, mode_t perm,
int create_socket(const char *name, int type, mode_t perm,
                  uid_t uid, gid_t gid, const char *socketcon);
                  uid_t uid, gid_t gid, const char *socketcon);


bool read_file(const char* path, std::string* content);
bool read_file(const std::string& path, std::string* content);
bool write_file(const char* path, const char* content);
bool write_file(const std::string& path, const std::string& content);


// A std::chrono clock based on CLOCK_BOOTTIME.
// A std::chrono clock based on CLOCK_BOOTTIME.
class boot_clock {
class boot_clock {
+18 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@


#include <errno.h>
#include <errno.h>


#include <android-base/test_utils.h>
#include <gtest/gtest.h>
#include <gtest/gtest.h>


TEST(util, read_file_ENOENT) {
TEST(util, read_file_ENOENT) {
@@ -37,6 +38,23 @@ TEST(util, read_file_success) {
  EXPECT_STREQ("Linux", s.c_str());
  EXPECT_STREQ("Linux", s.c_str());
}
}


TEST(util, write_file_binary) {
    std::string contents("abcd");
    contents.push_back('\0');
    contents.push_back('\0');
    contents.append("dcba");
    ASSERT_EQ(10u, contents.size());

    TemporaryFile tf;
    ASSERT_TRUE(tf.fd != -1);
    EXPECT_TRUE(write_file(tf.path, contents)) << strerror(errno);

    std::string read_back_contents;
    EXPECT_TRUE(read_file(tf.path, &read_back_contents)) << strerror(errno);
    EXPECT_EQ(contents, read_back_contents);
    EXPECT_EQ(10u, read_back_contents.size());
}

TEST(util, decode_uid) {
TEST(util, decode_uid) {
  EXPECT_EQ(0U, decode_uid("root"));
  EXPECT_EQ(0U, decode_uid("root"));
  EXPECT_EQ(UINT_MAX, decode_uid("toot"));
  EXPECT_EQ(UINT_MAX, decode_uid("toot"));