9#include <config-kiocore.h>
14#include "../aclhelpers_p.h"
25class Q_DECL_HIDDEN
KACL::KACLPrivate
35 explicit KACLPrivate(acl_t acl)
50 bool setMaskPermissions(
unsigned short v);
51 QString getUserName(uid_t uid)
const;
52 QString getGroupName(gid_t gid)
const;
53 bool setAllUsersOrGroups(
const QList<QPair<QString, unsigned short>> &list, acl_tag_t type);
54 bool setNamedUserOrGroupPermissions(
const QString &name,
unsigned short permissions, acl_tag_t type);
70 : d(
new KACLPrivate(ACLPortability::acl_from_mode(basePermissions)))
76 Q_UNUSED(basePermissions);
91KACL::~KACL() =
default;
93KACL &KACL::operator=(
const KACL &rhs)
101bool KACL::operator==(
const KACL &rhs)
const
104 return (ACLPortability::acl_cmp(d->m_acl, rhs.d->m_acl) == 0);
111bool KACL::operator!=(
const KACL &rhs)
const
113 return !operator==(rhs);
121 valid = (acl_valid(d->m_acl) == 0);
130 return (ACLPortability::acl_equiv_mode(d->m_acl,
nullptr) != 0);
137static acl_entry_t entryForTag(acl_t acl, acl_tag_t tag)
140 int ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
142 acl_tag_t currentTag;
143 acl_get_tag_type(entry, ¤tTag);
144 if (currentTag == tag) {
147 ret = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
152static unsigned short entryToPermissions(acl_entry_t entry)
154 if (entry ==
nullptr) {
157 acl_permset_t permset;
158 if (acl_get_permset(entry, &permset) != 0) {
161 return (ACLPortability::acl_get_perm(permset, ACL_READ) << 2 | ACLPortability::acl_get_perm(permset, ACL_WRITE) << 1
162 | ACLPortability::acl_get_perm(permset, ACL_EXECUTE));
165static void permissionsToEntry(acl_entry_t entry,
unsigned short v)
167 if (entry ==
nullptr) {
170 acl_permset_t permset;
171 if (acl_get_permset(entry, &permset) != 0) {
174 acl_clear_perms(permset);
176 acl_add_perm(permset, ACL_READ);
179 acl_add_perm(permset, ACL_WRITE);
182 acl_add_perm(permset, ACL_EXECUTE);
186static int getUidForName(
const QString &name)
196static int getGidForName(
const QString &name)
200 return group->gr_gid;
211 return entryToPermissions(entryForTag(d->m_acl, ACL_USER_OBJ));
220 permissionsToEntry(entryForTag(d->m_acl, ACL_USER_OBJ), v);
230 return entryToPermissions(entryForTag(d->m_acl, ACL_GROUP_OBJ));
239 permissionsToEntry(entryForTag(d->m_acl, ACL_GROUP_OBJ), v);
249 return entryToPermissions(entryForTag(d->m_acl, ACL_OTHER));
258 permissionsToEntry(entryForTag(d->m_acl, ACL_OTHER), v);
304 acl_entry_t entry = entryForTag(d->m_acl, ACL_MASK);
305 if (entry ==
nullptr) {
309 return entryToPermissions(entry);
316bool KACL::KACLPrivate::setMaskPermissions(
unsigned short v)
318 acl_entry_t entry = entryForTag(m_acl, ACL_MASK);
319 if (entry ==
nullptr) {
320 acl_create_entry(&m_acl, &entry);
321 acl_set_tag_type(entry, ACL_MASK);
323 permissionsToEntry(entry, v);
331 return d->setMaskPermissions(v);
339using unique_ptr_acl_free = std::unique_ptr<void, int (*)(
void *)>;
350 int ret = acl_get_entry(d->m_acl, ACL_FIRST_ENTRY, &entry);
352 acl_tag_t currentTag;
353 acl_get_tag_type(entry, ¤tTag);
354 if (currentTag == ACL_USER) {
355 const unique_ptr_acl_free idptr(acl_get_qualifier(entry), acl_free);
356 const uid_t
id = *(
static_cast<uid_t *
>(idptr.get()));
357 if (d->getUserName(
id) == name) {
359 return entryToPermissions(entry);
362 ret = acl_get_entry(d->m_acl, ACL_NEXT_ENTRY, &entry);
372bool KACL::KACLPrivate::setNamedUserOrGroupPermissions(
const QString &name,
unsigned short permissions, acl_tag_t type)
374 bool allIsWell =
true;
375 acl_t newACL = acl_dup(m_acl);
377 bool createdNewEntry =
false;
379 int ret = acl_get_entry(newACL, ACL_FIRST_ENTRY, &entry);
381 acl_tag_t currentTag;
382 acl_get_tag_type(entry, ¤tTag);
383 if (currentTag == type) {
384 const unique_ptr_acl_free idptr(acl_get_qualifier(entry), acl_free);
385 const int id = *(
static_cast<int *
>(idptr.get()));
386 const QString entryName = type == ACL_USER ? getUserName(
id) : getGroupName(id);
387 if (entryName == name) {
389 permissionsToEntry(entry, permissions);
394 ret = acl_get_entry(newACL, ACL_NEXT_ENTRY, &entry);
397 acl_create_entry(&newACL, &entry);
398 acl_set_tag_type(entry, type);
399 int id =
type == ACL_USER ? getUidForName(name) : getGidForName(
name);
400 if (
id == -1 || acl_set_qualifier(entry, &
id) != 0) {
401 acl_delete_entry(newACL, entry);
404 permissionsToEntry(entry, permissions);
405 createdNewEntry =
true;
408 if (allIsWell && createdNewEntry) {
412 if (entryForTag(newACL, ACL_MASK) ==
nullptr) {
413 acl_calc_mask(&newACL);
417 if (!allIsWell || acl_valid(newACL) != 0) {
431 return d->setNamedUserOrGroupPermissions(name, permissions, ACL_USER);
434 Q_UNUSED(permissions);
444 int ret = acl_get_entry(d->m_acl, ACL_FIRST_ENTRY, &entry);
446 acl_tag_t currentTag;
447 acl_get_tag_type(entry, ¤tTag);
448 if (currentTag == ACL_USER) {
449 const unique_ptr_acl_free idptr(acl_get_qualifier(entry), acl_free);
450 const uid_t
id = *(
static_cast<uid_t *
>(idptr.get()));
451 QString name = d->getUserName(
id);
452 unsigned short permissions = entryToPermissions(entry);
453 ACLUserPermissions pair = qMakePair(name, permissions);
456 ret = acl_get_entry(d->m_acl, ACL_NEXT_ENTRY, &entry);
463bool KACL::KACLPrivate::setAllUsersOrGroups(
const QList<QPair<QString, unsigned short>> &list, acl_tag_t type)
465 bool allIsWell =
true;
466 bool atLeastOneUserOrGroup =
false;
469 acl_t newACL = acl_dup(m_acl);
473 int ret = acl_get_entry(newACL, ACL_FIRST_ENTRY, &entry);
475 acl_tag_t currentTag;
476 acl_get_tag_type(entry, ¤tTag);
477 if (currentTag == type) {
478 acl_delete_entry(newACL, entry);
481 ret = acl_get_entry(newACL, ACL_FIRST_ENTRY, &entry);
483 ret = acl_get_entry(newACL, ACL_NEXT_ENTRY, &entry);
488 for (
const auto &[name, userId] : list) {
489 acl_create_entry(&newACL, &entry);
490 acl_set_tag_type(entry, type);
491 int id =
type == ACL_USER ? getUidForName(name) : getGidForName(
name);
492 if (
id == -1 || acl_set_qualifier(entry, &
id) != 0) {
494 acl_delete_entry(newACL, entry);
498 permissionsToEntry(entry, userId);
499 atLeastOneUserOrGroup =
true;
503 if (allIsWell && atLeastOneUserOrGroup) {
507 if (entryForTag(newACL, ACL_MASK) ==
nullptr) {
508 acl_calc_mask(&newACL);
511 if (allIsWell && (acl_valid(newACL) == 0)) {
524 return d->setAllUsersOrGroups(users, ACL_USER);
540 int ret = acl_get_entry(d->m_acl, ACL_FIRST_ENTRY, &entry);
542 acl_tag_t currentTag;
543 acl_get_tag_type(entry, ¤tTag);
544 if (currentTag == ACL_GROUP) {
545 const unique_ptr_acl_free idptr(acl_get_qualifier(entry), acl_free);
546 const gid_t
id = *(
static_cast<gid_t *
>(idptr.get()));
547 if (d->getGroupName(
id) == name) {
549 return entryToPermissions(entry);
552 ret = acl_get_entry(d->m_acl, ACL_NEXT_ENTRY, &entry);
563 return d->setNamedUserOrGroupPermissions(name, permissions, ACL_GROUP);
566 Q_UNUSED(permissions);
576 int ret = acl_get_entry(d->m_acl, ACL_FIRST_ENTRY, &entry);
578 acl_tag_t currentTag;
579 acl_get_tag_type(entry, ¤tTag);
580 if (currentTag == ACL_GROUP) {
581 const unique_ptr_acl_free idptr(acl_get_qualifier(entry), acl_free);
582 const gid_t
id = *(
static_cast<gid_t *
>(idptr.get()));
583 QString name = d->getGroupName(
id);
584 unsigned short permissions = entryToPermissions(entry);
585 ACLGroupPermissions pair = qMakePair(name, permissions);
588 ret = acl_get_entry(d->m_acl, ACL_NEXT_ENTRY, &entry);
597 return d->setAllUsersOrGroups(groups, ACL_GROUP);
613 if (acl_valid(temp) != 0) {
633 char *txt = acl_to_text(d->m_acl, &size);
645QString KACL::KACLPrivate::getUserName(uid_t uid)
const
647 auto it = m_usercache.find(uid);
648 if (it == m_usercache.end()) {
649 struct passwd *user = getpwuid(uid);
659QString KACL::KACLPrivate::getGroupName(gid_t gid)
const
661 auto it = m_groupcache.find(gid);
662 if (it == m_groupcache.end()) {
663 struct group *grp = getgrgid(gid);
674void KACL::virtual_hook(
int,
void *)
The KACL class encapsulates a POSIX Access Control List.
KACL()
Creates an empty KACL.
bool setNamedGroupPermissions(const QString &name, unsigned short)
Set the permissions for a group with the name name.
unsigned short maskPermissions(bool &exists) const
Return the entry for the permissions mask if there is one and sets exists to true.
unsigned short namedGroupPermissions(const QString &name, bool *exists) const
Access to the permissions entry for a named group, if such an entry exists.
unsigned short namedUserPermissions(const QString &name, bool *exists) const
Access to the permissions entry for a named user, if such an entry exists.
bool isExtended() const
The interface to the extended ACL.
bool setOthersPermissions(unsigned short)
Set the permissions entry for others.
bool setMaskPermissions(unsigned short)
Set the permissions mask for the ACL.
bool setACL(const QString &aclStr)
Sets the whole list from a string.
mode_t basePermissions() const
bool isValid() const
Returns whether the KACL object represents a valid acl.
bool setOwningGroupPermissions(unsigned short)
Set the owning group's permissions entry.
ACLGroupPermissionsList allGroupPermissions() const
Returns the list of all group permission entries.
bool setOwnerPermissions(unsigned short)
Set the owner's permissions entry.
unsigned short othersPermissions() const
bool setAllUserPermissions(const ACLUserPermissionsList &list)
Replace the list of all user permissions with list.
bool setNamedUserPermissions(const QString &name, unsigned short)
Set the permissions for a user with the name name.
ACLUserPermissionsList allUserPermissions() const
Returns the list of all group permission entries.
QString asString() const
Return a string representation of the ACL.
bool setAllGroupPermissions(const ACLGroupPermissionsList &)
Replace the list of all user permissions with list.
unsigned short ownerPermissions() const
The standard (non-extended) part of an ACL.
unsigned short owningGroupPermissions() const
Type type(const QSqlDatabase &db)
A namespace for KIO globals.
QString name(StandardAction id)
const char * constData() const const
void append(QList< T > &&value)
QString fromLatin1(QByteArrayView str)
QString number(double n, char format, int precision)
QByteArray toLatin1() const const
QByteArray toLocal8Bit() const const