diff --git a/util/mac/xattr.cc b/util/mac/xattr.cc index 750a056d..54a8a09a 100644 --- a/util/mac/xattr.cc +++ b/util/mac/xattr.cc @@ -14,6 +14,7 @@ #include "util/mac/xattr.h" +#include #include #include @@ -25,15 +26,17 @@ namespace crashpad { -bool ReadXattr(const base::FilePath& file, - const base::StringPiece& name, - std::string* value) { +XattrStatus ReadXattr(const base::FilePath& file, + const base::StringPiece& name, + std::string* value) { // First get the size of the attribute value. ssize_t buffer_size = getxattr(file.value().c_str(), name.data(), nullptr, 0, 0, 0); if (buffer_size < 0) { + if (errno == ENOATTR) + return XattrStatus::kNoAttribute; PLOG(ERROR) << "getxattr size " << name << " on file " << file.value(); - return false; + return XattrStatus::kOtherError; } // Resize the buffer and read into it. @@ -43,11 +46,11 @@ bool ReadXattr(const base::FilePath& file, 0, 0); if (bytes_read < 0) { PLOG(ERROR) << "getxattr " << name << " on file " << file.value(); - return false; + return XattrStatus::kOtherError; } DCHECK_EQ(bytes_read, buffer_size); - return true; + return XattrStatus::kOK; } bool WriteXattr(const base::FilePath& file, @@ -60,22 +63,23 @@ bool WriteXattr(const base::FilePath& file, return rv == 0; } -bool ReadXattrBool(const base::FilePath& file, - const base::StringPiece& name, - bool* value) { +XattrStatus ReadXattrBool(const base::FilePath& file, + const base::StringPiece& name, + bool* value) { std::string tmp; - if (!ReadXattr(file, name, &tmp)) - return false; + XattrStatus status; + if ((status = ReadXattr(file, name, &tmp)) != XattrStatus::kOK) + return status; if (tmp == "1") { *value = true; - return true; + return XattrStatus::kOK; } else if (tmp == "0") { *value = false; - return true; + return XattrStatus::kOK; } else { LOG(ERROR) << "ReadXattrBool " << name << " on file " << file.value() << " could not be interpreted as boolean"; - return false; + return XattrStatus::kOtherError; } } @@ -85,18 +89,19 @@ bool WriteXattrBool(const base::FilePath& file, return WriteXattr(file, name, (value ? "1" : "0")); } -bool ReadXattrInt(const base::FilePath& file, - const base::StringPiece& name, - int* value) { +XattrStatus ReadXattrInt(const base::FilePath& file, + const base::StringPiece& name, + int* value) { std::string tmp; - if (!ReadXattr(file, name, &tmp)) - return false; + XattrStatus status; + if ((status = ReadXattr(file, name, &tmp)) != XattrStatus::kOK) + return status; if (!base::StringToInt(tmp, value)) { LOG(ERROR) << "ReadXattrInt " << name << " on file " << file.value() << " could not be converted to an int"; - return false; + return XattrStatus::kOtherError; } - return true; + return XattrStatus::kOK; } bool WriteXattrInt(const base::FilePath& file, @@ -106,30 +111,31 @@ bool WriteXattrInt(const base::FilePath& file, return WriteXattr(file, name, tmp); } -bool ReadXattrTimeT(const base::FilePath& file, - const base::StringPiece& name, - time_t* value) { +XattrStatus ReadXattrTimeT(const base::FilePath& file, + const base::StringPiece& name, + time_t* value) { // time_t on OS X is defined as a long, but it will be read into an // int64_t here, since there is no string conversion method for long. std::string tmp; - if (!ReadXattr(file, name, &tmp)) - return false; + XattrStatus status; + if ((status = ReadXattr(file, name, &tmp)) != XattrStatus::kOK) + return status; int64_t encoded_value; if (!base::StringToInt64(tmp, &encoded_value)) { LOG(ERROR) << "ReadXattrTimeT " << name << " on file " << file.value() << " could not be converted to an int"; - return false; + return XattrStatus::kOtherError; } *value = base::saturated_cast(encoded_value); if (!base::IsValueInRangeForNumericType(encoded_value)) { LOG(ERROR) << "ReadXattrTimeT " << name << " on file " << file.value() << " read over-sized value and will saturate"; - return false; + return XattrStatus::kOtherError; } - return true; + return XattrStatus::kOK; } bool WriteXattrTimeT(const base::FilePath& file, diff --git a/util/mac/xattr.h b/util/mac/xattr.h index b816f390..3e14f672 100644 --- a/util/mac/xattr.h +++ b/util/mac/xattr.h @@ -24,17 +24,28 @@ namespace crashpad { +//! \brief The result code for a ReadXattr operation. +enum class XattrStatus { + //! \brief No error occured. No message is logged. + kOK = 0, + + //! \brief The attribute does not exist. No message is logged. + kNoAttribute, + + //! \brief An error occurred and an error message was logged. + kOtherError, +}; + //! \brief Reads an extended attribute on a file. //! //! \param[in] file The path to the file. //! \param[in] name The name of the extended attribute to read. //! \param[out] value The value of the attribute. //! -//! \return `true` if the read was successful, with \a value filled in. `false` -//! on error, with a message logged. -bool ReadXattr(const base::FilePath& file, - const base::StringPiece& name, - std::string* value); +//! \return XattrStatus +XattrStatus ReadXattr(const base::FilePath& file, + const base::StringPiece& name, + std::string* value); //! \brief Writes an extended attribute on a file. //! @@ -52,9 +63,9 @@ bool WriteXattr(const base::FilePath& file, //! //! Only the values `"0"` and `"1"`, for `false` and `true` respectively, are //! valid conversions. -bool ReadXattrBool(const base::FilePath& file, - const base::StringPiece& name, - bool* value); +XattrStatus ReadXattrBool(const base::FilePath& file, + const base::StringPiece& name, + bool* value); //! \copydoc WriteXattr bool WriteXattrBool(const base::FilePath& file, @@ -62,9 +73,9 @@ bool WriteXattrBool(const base::FilePath& file, bool value); //! \copydoc ReadXattr -bool ReadXattrInt(const base::FilePath& file, - const base::StringPiece& name, - int* value); +XattrStatus ReadXattrInt(const base::FilePath& file, + const base::StringPiece& name, + int* value); //! \copydoc WriteXattr bool WriteXattrInt(const base::FilePath& file, @@ -72,9 +83,9 @@ bool WriteXattrInt(const base::FilePath& file, int value); //! \copydoc ReadXattr -bool ReadXattrTimeT(const base::FilePath& file, - const base::StringPiece& name, - time_t* value); +XattrStatus ReadXattrTimeT(const base::FilePath& file, + const base::StringPiece& name, + time_t* value); //! \copydoc WriteXattr bool WriteXattrTimeT(const base::FilePath& file, diff --git a/util/mac/xattr_test.cc b/util/mac/xattr_test.cc index c02aa08c..a25cfbb5 100644 --- a/util/mac/xattr_test.cc +++ b/util/mac/xattr_test.cc @@ -57,7 +57,7 @@ const char kKey[] = "com.google.crashpad.test"; TEST_F(Xattr, ReadNonExistentXattr) { std::string value; - EXPECT_FALSE(ReadXattr(path(), kKey, &value)); + EXPECT_EQ(XattrStatus::kNoAttribute, ReadXattr(path(), kKey, &value)); } TEST_F(Xattr, WriteAndReadString) { @@ -65,7 +65,7 @@ TEST_F(Xattr, WriteAndReadString) { EXPECT_TRUE(WriteXattr(path(), kKey, value)); std::string actual; - EXPECT_TRUE(ReadXattr(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattr(path(), kKey, &actual)); EXPECT_EQ(value, actual); } @@ -74,18 +74,18 @@ TEST_F(Xattr, WriteAndReadVeryLongString) { EXPECT_TRUE(WriteXattr(path(), kKey, value)); std::string actual; - EXPECT_TRUE(ReadXattr(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattr(path(), kKey, &actual)); EXPECT_EQ(value, actual); } TEST_F(Xattr, WriteAndReadBool) { EXPECT_TRUE(WriteXattrBool(path(), kKey, true)); bool actual = false; - EXPECT_TRUE(ReadXattrBool(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrBool(path(), kKey, &actual)); EXPECT_TRUE(actual); EXPECT_TRUE(WriteXattrBool(path(), kKey, false)); - EXPECT_TRUE(ReadXattrBool(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrBool(path(), kKey, &actual)); EXPECT_FALSE(actual); } @@ -94,12 +94,12 @@ TEST_F(Xattr, WriteAndReadInt) { int actual; EXPECT_TRUE(WriteXattrInt(path(), kKey, expected)); - EXPECT_TRUE(ReadXattrInt(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrInt(path(), kKey, &actual)); EXPECT_EQ(expected, actual); expected = std::numeric_limits::max(); EXPECT_TRUE(WriteXattrInt(path(), kKey, expected)); - EXPECT_TRUE(ReadXattrInt(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrInt(path(), kKey, &actual)); EXPECT_EQ(expected, actual); } @@ -108,12 +108,12 @@ TEST_F(Xattr, WriteAndReadTimeT) { time_t actual; EXPECT_TRUE(WriteXattrTimeT(path(), kKey, expected)); - EXPECT_TRUE(ReadXattrTimeT(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrTimeT(path(), kKey, &actual)); EXPECT_EQ(expected, actual); expected = std::numeric_limits::max(); EXPECT_TRUE(WriteXattrTimeT(path(), kKey, expected)); - EXPECT_TRUE(ReadXattrTimeT(path(), kKey, &actual)); + EXPECT_EQ(XattrStatus::kOK, ReadXattrTimeT(path(), kKey, &actual)); EXPECT_EQ(expected, actual); }