File indexing completed on 2024-04-14 03:53:40

0001 /*
0002     SPDX-FileCopyrightText: 2000-2002 Till Adam <adam@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef ACLHELPERS_P_H
0008 #define ACLHELPERS_P_H
0009 
0010 /*************************************
0011  *
0012  * ACL handling helpers
0013  *
0014  *************************************/
0015 
0016 #include <config-kiocore.h>
0017 
0018 #include "utils_p.h"
0019 #include <KIO/UDSEntry>
0020 
0021 #include <sys/types.h>
0022 
0023 #if HAVE_SYS_ACL_H
0024 #include <sys/acl.h>
0025 #endif
0026 #if HAVE_ACL_LIBACL_H
0027 #include <acl/libacl.h>
0028 #endif
0029 
0030 namespace KIO
0031 {
0032 /**
0033  * @internal
0034  * WARNING: DO NOT USE outside KIO Framework
0035  */
0036 namespace ACLPortability
0037 {
0038 /// @internal
0039 __attribute__((unused)) static inline int acl_cmp(acl_t acl1, acl_t acl2)
0040 {
0041 #ifdef Q_OS_FREEBSD
0042     return ::acl_cmp_np(acl1, acl2);
0043 #else
0044     return ::acl_cmp(acl1, acl2);
0045 #endif
0046 }
0047 
0048 /// @internal
0049 __attribute__((unused)) static inline acl_t acl_from_mode(const mode_t mode)
0050 {
0051 #ifdef Q_OS_FREEBSD
0052     return ::acl_from_mode_np(mode);
0053 #else
0054     return ::acl_from_mode(mode);
0055 #endif
0056 }
0057 
0058 /// @internal
0059 static inline int acl_equiv_mode(acl_t acl, mode_t *mode_p)
0060 {
0061 #ifdef Q_OS_FREEBSD
0062     return ::acl_equiv_mode_np(acl, mode_p);
0063 #else
0064     return ::acl_equiv_mode(acl, mode_p);
0065 #endif
0066 }
0067 
0068 /// @internal
0069 __attribute__((unused)) static inline int acl_get_perm(acl_permset_t permset_d, acl_perm_t perm)
0070 {
0071 #ifdef Q_OS_FREEBSD
0072     return ::acl_get_perm_np(permset_d, perm);
0073 #else
0074     return ::acl_get_perm(permset_d, perm);
0075 #endif
0076 }
0077 
0078 /// @internal
0079 __attribute__((unused)) static inline int acl_extended_file(const char *path_p)
0080 {
0081 #ifdef Q_OS_FREEBSD
0082     return ::acl_extended_file_np(path_p);
0083 #else
0084     return ::acl_extended_file(path_p);
0085 #endif
0086 }
0087 
0088 } // namespace ACLPortability
0089 } // namespace KIO
0090 
0091 static QString aclToText(acl_t acl)
0092 {
0093     ssize_t size = 0;
0094     char *txt = acl_to_text(acl, &size);
0095     const QString ret = QString::fromLatin1(txt, size);
0096     acl_free(txt);
0097     return ret;
0098 }
0099 
0100 /* Append an atom indicating whether the file has extended acl information
0101  * and if withACL is specified also one with the acl itself. If it's a directory
0102  * and it has a default ACL, also append that. */
0103 __attribute__((unused)) static void appendACLAtoms(const QByteArray &path, KIO::UDSEntry &entry, mode_t type)
0104 {
0105     // first check for a noop
0106     if (KIO::ACLPortability::acl_extended_file(path.data()) == 0) {
0107         return;
0108     }
0109 
0110     acl_t acl = nullptr;
0111     acl_t defaultAcl = nullptr;
0112     // do we have an acl for the file, and/or a default acl for the dir, if it is one?
0113     acl = acl_get_file(path.data(), ACL_TYPE_ACCESS);
0114     /* Sadly libacl does not provided a means of checking for extended ACL and default
0115      * ACL separately. Since a directory can have both, we need to check again. */
0116     if (Utils::isDirMask(type)) {
0117         if (acl) {
0118             if (KIO::ACLPortability::acl_equiv_mode(acl, nullptr) == 0) {
0119                 acl_free(acl);
0120                 acl = nullptr;
0121             }
0122         }
0123         defaultAcl = acl_get_file(path.data(), ACL_TYPE_DEFAULT);
0124     }
0125 
0126     if (acl || defaultAcl) {
0127         // qDebug() << path.constData() << "has extended ACL entries";
0128         entry.replace(KIO::UDSEntry::UDS_EXTENDED_ACL, 1);
0129 
0130         if (acl) {
0131             const QString str = aclToText(acl);
0132             entry.replace(KIO::UDSEntry::UDS_ACL_STRING, str);
0133             // qDebug() << path.constData() << "ACL:" << str;
0134             acl_free(acl);
0135         }
0136 
0137         if (defaultAcl) {
0138             const QString str = aclToText(defaultAcl);
0139             entry.replace(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, str);
0140             // qDebug() << path.constData() << "DEFAULT ACL:" << str;
0141             acl_free(defaultAcl);
0142         }
0143     }
0144 }
0145 
0146 #endif // ACLHELPERS_P_H