diff --git a/src/libcalamares/utils/Permissions.cpp b/src/libcalamares/utils/Permissions.cpp index 3f5350e86..a7afbc5fc 100644 --- a/src/libcalamares/utils/Permissions.cpp +++ b/src/libcalamares/utils/Permissions.cpp @@ -8,11 +8,14 @@ #include "Permissions.h" -#include +#include "Logger.h" +#include #include #include +#include + namespace CalamaresUtils { @@ -73,8 +76,49 @@ Permissions::parsePermissions( QString const& p ) bool Permissions::apply( const QString& path, int mode ) { - int r = chmod( path.toUtf8().constData(), mode ); + // We **don't** use QFile::setPermissions() here because it takes + // a Qt flags object that subtlely does not align with POSIX bits. + // The Qt flags are **hex** based, so 0x755 for rwxr-xr-x, while + // our integer (mode_t) stores **octal** based flags. + // + // Call chmod(2) directly, that's what Qt would be doing underneath + // anyway. + int r = chmod( path.toUtf8().constData(), mode_t( mode ) ); + if ( r ) + { + cDebug() << Logger::SubEntry << "Could not set permissions of" << path << "to" << QString::number( mode, 8 ); + } return r == 0; } +bool +Permissions::apply( const QString& path, const CalamaresUtils::Permissions& p ) +{ + if ( !p.isValid() ) + { + return false; + } + bool r = apply( path, p.value() ); + if ( r ) + { + // We don't use chgrp(2) or chown(2) here because then we need to + // go through the users list (which one, target or source?) to get + // uid_t and gid_t values to pass to that system call. + // + // Do a lame cop-out and let the chown(8) utility do the heavy lifting. + if ( QProcess::execute( "chown", { p.username() + ':' + p.group(), path } ) ) + { + r = false; + cDebug() << Logger::SubEntry << "Could not set owner of" << path << "to" + << ( p.username() + ':' + p.group() ); + } + } + if ( r ) + { + /* NOTUSED */ apply( path, p.value() ); + } + return r; +} + + } // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Permissions.h b/src/libcalamares/utils/Permissions.h index 913d037d5..1f0dd38da 100644 --- a/src/libcalamares/utils/Permissions.h +++ b/src/libcalamares/utils/Permissions.h @@ -49,7 +49,7 @@ public: * * Bear in mind that input is in octal, but integers are just integers; * naively printing them will get decimal results (e.g. 493 from the - * input of "root:wheel:755"). + * input of "root:wheel:755"). This is suitable to pass to apply(). */ int value() const { return m_value; } /** @brief The value (file permission) as octal string @@ -59,8 +59,24 @@ public: */ QString octal() const { return QString::number( value(), 8 ); } - /// chmod(path, mode), returns true on success + /** @brief Sets the file-access @p mode of @p path + * + * Pass a path that is relative (or absolute) in the **host** system. + */ static bool apply( const QString& path, int mode ); + /** @brief Do both chmod and chown on @p path + * + * Note that interpreting user- and group- names for applying the + * permissions can be different between the host system and the target + * system; the target might not have a "live" user, for instance, and + * the host won't have the user-entered username for the installation. + * + * For this call, the names are interpreted in the **host** system. + * Pass a path that is relative (or absolute) in the **host** system. + */ + static bool apply( const QString& path, const Permissions& p ); + /// Convenience method for apply(const QString&, const Permissions& ) + bool apply( const QString& path ) const { return apply( path, *this ); } private: void parsePermissions( QString const& p );