From 206dfce40957bce2923e6084f2891d01cdcbbe81 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 22 Oct 2024 16:52:59 +0200 Subject: [PATCH] [libcalamares] Add an "rwx" mode for permissions (and tests) --- src/libcalamares/utils/Permissions.cpp | 60 ++++++++++++++++++++++++++ src/libcalamares/utils/Permissions.h | 1 + src/libcalamares/utils/Tests.cpp | 8 +++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/Permissions.cpp b/src/libcalamares/utils/Permissions.cpp index a67932fdc..aac47a2d9 100644 --- a/src/libcalamares/utils/Permissions.cpp +++ b/src/libcalamares/utils/Permissions.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * SPDX-FileCopyrightText: 2018 Scott Harvey + * SPDX-FileCopyrightText: 2024 Adriaan de Groot * SPDX-License-Identifier: GPL-3.0-or-later * */ @@ -15,6 +16,44 @@ #include +// Massaged and re-named from https://euroquis.nl/blabla/2024/04/30/chmod.html for C++17 +namespace +{ + +template < int position, char accept > +int +expectCharacterAtPosition( const QString& s ) +{ + const QChar unicode = s.at( position ); + if ( unicode.row() != 0 ) + { + return -1; + } + + const char c = char( unicode.cell() ); // cell() returns uchar + if ( c == accept ) + { + return 1 << ( 8 - position ); + } + if ( c == '-' ) + { + return 0; + } + return -1; +} + +int +modeFromVerboseString( const QString& s ) +{ + return expectCharacterAtPosition< 0, 'r' >( s ) | expectCharacterAtPosition< 1, 'w' >( s ) + | expectCharacterAtPosition< 3, 'r' >( s ) | expectCharacterAtPosition< 2, 'x' >( s ) + | expectCharacterAtPosition< 4, 'w' >( s ) | expectCharacterAtPosition< 5, 'x' >( s ) + | expectCharacterAtPosition< 6, 'r' >( s ) | expectCharacterAtPosition< 7, 'w' >( s ) + | expectCharacterAtPosition< 8, 'x' >( s ); +} + +} // namespace + namespace Calamares { @@ -119,6 +158,7 @@ Permissions::apply( const QString& path, const Calamares::Permissions& p ) return r; } +///@brief Assumes an octal 3-digit (at most) value static int parseOctalFileMode( const QString& mode ) { @@ -139,6 +179,21 @@ parseOctalFileMode( const QString& mode ) return octal; } +///@brief Checks for "rwx"-style modes, which must be 9 characters and start with a - or an r +static bool +isRWXMode( const QString& mode ) +{ + if ( mode.length() != 9 ) + { + return false; + } + if ( mode.startsWith( '-' ) || mode.startsWith( 'r' ) ) + { + return true; + } + return false; +} + int parseFileMode( const QString& mode ) { @@ -146,6 +201,11 @@ parseFileMode( const QString& mode ) { return parseOctalFileMode( mode.mid( 1 ) ); } + if ( isRWXMode( mode ) ) + { + return modeFromVerboseString( mode ); + } + return parseOctalFileMode( mode ); } diff --git a/src/libcalamares/utils/Permissions.h b/src/libcalamares/utils/Permissions.h index 1062dbd98..02ffc9c74 100644 --- a/src/libcalamares/utils/Permissions.h +++ b/src/libcalamares/utils/Permissions.h @@ -104,6 +104,7 @@ private: * - octal representation with a leading 'o' (letter) and at most three * octal digits (e.g. o755 or o644). Use this in YAML where a string * of digits would otherwise be interpreted as a (base-10) integer. + * - "rwx" representation with exactly 9 characters like the output of ls. */ DLLEXPORT int parseFileMode( const QString& mode ); diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index e669f4157..e1a298a90 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -583,10 +583,14 @@ LibCalamaresTests::testPermissions() QCOMPARE( Calamares::parseFileMode( QStringLiteral( " %1\n" ).arg( repr ) ), i ); } + // "rwx" style + QCOMPARE( Calamares::parseFileMode( QStringLiteral( "rwxr-----" ) ), 0740 ); + QCOMPARE( Calamares::parseFileMode( QStringLiteral( "rwxr-x-w-" ) ), 0752 ); + // With leading octal 'o' + QCOMPARE( Calamares::parseFileMode( QStringLiteral( "o644" ) ), 0644 ); + // Failures QCOMPARE( Calamares::parseFileMode( QStringLiteral( "1024" ) ), -1 ); - QCOMPARE( Calamares::parseFileMode( QStringLiteral( "rwxr-----" ) ), -1 ); - QCOMPARE( Calamares::parseFileMode( QStringLiteral( "o644" ) ), -1 ); QCOMPARE( Calamares::parseFileMode( QStringLiteral( "O_WRONLY" ) ), -1 ); }