228 lines
5.3 KiB
C++
228 lines
5.3 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2019, Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include "acl.hpp"
|
|
|
|
#include <acl/libacl.h>
|
|
|
|
#include <cruft/util/posix/except.hpp>
|
|
#include <cruft/util/scoped.hpp>
|
|
#include <cruft/util/iterator/infix.hpp>
|
|
|
|
|
|
using cruft::acl;
|
|
using cruft::entry;
|
|
using cruft::permset;
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
acl::acl (int count)
|
|
: acl (acl_init (count))
|
|
{ ; }
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::acl (std::filesystem::path const &path, acl_type_t type)
|
|
: acl (acl_get_file (path.native ().c_str (), type))
|
|
{ ; }
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::acl (acl_t &&_native)
|
|
: m_native (_native)
|
|
{
|
|
if (!m_native)
|
|
cruft::posix::error::throw_code ();
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
acl::~acl ()
|
|
{
|
|
if (m_native)
|
|
acl_free (m_native);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
acl acl::dup (void) const
|
|
{
|
|
return acl {
|
|
acl_dup (m_native)
|
|
};
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
acl::iterator::iterator (acl const &_parent)
|
|
: m_parent (&_parent)
|
|
{
|
|
fetch (ACL_FIRST_ENTRY);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::iterator::iterator ()
|
|
: m_parent (nullptr)
|
|
{ ; }
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::iterator::value_type
|
|
acl::iterator::operator* (void)
|
|
{
|
|
return entry { m_value };
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::iterator&
|
|
acl::iterator::operator++ ()
|
|
{
|
|
fetch (ACL_NEXT_ENTRY);
|
|
return *this;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool
|
|
acl::iterator::operator== (iterator const &rhs) const
|
|
{
|
|
return m_parent == rhs.m_parent;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool
|
|
acl::iterator::operator!= (iterator const &rhs) const
|
|
{
|
|
return m_parent != rhs.m_parent;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void
|
|
acl::iterator::fetch (int pos)
|
|
{
|
|
auto const res = acl_get_entry (m_parent->native (), pos, &m_value);
|
|
|
|
switch (res) {
|
|
case 0: m_parent = nullptr; return;
|
|
case 1: return;
|
|
default:
|
|
cruft::posix::error::throw_code ();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
acl::const_iterator
|
|
acl::begin (void) const
|
|
{
|
|
return const_iterator { *this };
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl::const_iterator
|
|
acl::end (void) const
|
|
{
|
|
return iterator {};
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int acl::size (void) const
|
|
{
|
|
return cruft::posix::error::try_call (acl_entries, m_native);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
entry::entry (acl_entry_t _native)
|
|
: m_native (_native)
|
|
{ ; }
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
acl_tag_t
|
|
entry::tag (void) const
|
|
{
|
|
acl_tag_t res;
|
|
cruft::posix::error::try_call (acl_get_tag_type, m_native, &res);
|
|
return res;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
class cruft::permset
|
|
entry::permset (void) const
|
|
{
|
|
acl_permset_t res;
|
|
cruft::posix::error::try_call (acl_get_permset, m_native, &res);
|
|
return res;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
permset::permset (acl_permset_t _native)
|
|
: m_native (_native)
|
|
{ ; }
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool permset::operator& (acl_perm_t val) const
|
|
{
|
|
return cruft::posix::error::try_call (acl_get_perm, m_native, val);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
std::ostream&
|
|
cruft::operator<< (std::ostream &os, cruft::acl const &val)
|
|
{
|
|
return os << "[ " << cruft::iterator::make_infix (val) << " ]";
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
std::ostream&
|
|
cruft::operator<< (std::ostream &os, cruft::entry const &val)
|
|
{
|
|
os << "{ ";
|
|
|
|
auto t = val.tag ();
|
|
|
|
switch (t) {
|
|
case ACL_USER: os << "uid: " << +val.qualifier<uid_t> (); break;
|
|
case ACL_GROUP: os << "gid: " << +val.qualifier<gid_t> (); break;
|
|
|
|
case ACL_USER_OBJ: os << "owner: null"; break;
|
|
case ACL_GROUP_OBJ: os << "group: null"; break;
|
|
case ACL_MASK: os << "mask: null"; break;
|
|
case ACL_OTHER: os << "other: null"; break;
|
|
default:
|
|
unhandled (t);
|
|
}
|
|
|
|
os << ", permset: " << val.permset () << " }";
|
|
|
|
return os;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
std::ostream&
|
|
cruft::operator<< (std::ostream &os, cruft::permset const &val)
|
|
{
|
|
return os << ((val & ACL_READ ) ? 'r' : '_')
|
|
<< ((val & ACL_WRITE ) ? 'w' : '_')
|
|
<< ((val & ACL_EXECUTE) ? 'x' : '_');
|
|
}
|