Skip to content

Conversation

@fabix
Copy link

@fabix fabix commented Jan 15, 2026

No description provided.

@steiler
Copy link
Owner

steiler commented Jan 16, 2026

Hi @fabix,
I had considered the ACLEntries immutable, thats why there are also no setters present on that struct.
If you use the same ACLEntry in multile ACLs but chnage it along the way, you might end up in a mess.
Does that make sense?

@fabix
Copy link
Author

fabix commented Jan 16, 2026

Hello @steiler,

Hi @fabix, I had considered the ACLEntries immutable, thats why there are also no setters present on that struct. If you use the same ACLEntry in multile ACLs but chnage it along the way, you might end up in a mess. Does that make sense?

In my use case, I need to inspect existing ACLs and sometimes modify them. It's not possible with the current implementation. Regarding using the same ACLEntry in multiple ACLs, I think that It is the developer's responsibility to know what he's doing. It's just working with pointers. I've added a Copy() method to get a "deep" copy of an ACL so the ACLEntries won't point to the same structs.

@steiler
Copy link
Owner

steiler commented Jan 16, 2026

If you say you need to chnage them, what does that mean? chnage the Perm on an ACLEntry or what is it exactly you're after?

@fabix
Copy link
Author

fabix commented Jan 16, 2026

That means that the user of the program has specified a new acl entry in a setfacl form (e.g. user:foo:rw-) and the program will check if this entry doesn't exist already (on the fs) and add it if it's not the case. I don't want to blindly apply the new ACL without knowing whether anything has changed or not.

@steiler
Copy link
Owner

steiler commented Jan 16, 2026

I've released a new version with the acl.GetEntry(...) func. With this you are able to do the below.
That should satisfy your requirements.

acl := &acls.ACL{}

err := acl.Load(filePath, acls.PosixACLAccess)
if err != nil {
	log.Errorf("Failed to load ACL: %v", err)
	return err
}

newEntry := acls.NewEntry(acls.TAG_ACL_USER, 1000, 6) // user:foo:rw-

if old := acl.GetEntry(newEntry); old != nil {
	log.Infof("Entry exists, replacing permissions")
	log.Debugf("Before: %s", old.String())
	acl.AddEntry(newEntry)
	log.Debugf("After: %s", newEntry.String())
} else {
	log.Infof("Entry doesn't exist, adding new entry")
	acl.AddEntry(newEntry)
}

log.Infof("Applying ACL changes to %s", filePath)
err = acl.Apply(filePath, acls.PosixACLAccess)
if err != nil {
	log.Errorf("Failed to apply ACL: %v", err)
	return err
}
log.Infof("ACL successfully applied")

@fabix
Copy link
Author

fabix commented Jan 16, 2026

Well, I need to compare a list of ACL rules defined in a configuration file with the current state. How can I know whether there are more rules than defined? For example, if a rule user:bar:rw- has been removed from the configuration file, I've no way of detecting that the ACL rule still exists on the fs with the current implementation. At best, I could only know that the ACL is not the same if I was able to define a "virtual" one but it's not possible to create one with version initialized at 2 so the Equal() will always return false... Sorry but it's much more flexible to have direct access to attributes. And with the new GetEntry() method, the ACL entries aren't immutable anymore anyway.

@steiler
Copy link
Owner

steiler commented Jan 16, 2026

Ok so what you are saying is that you need to get the List of ACLEntries in an ACL to basically sync the definition with the actual configuration. You did not point that out.

And with the new GetEntry() method, the ACL entries aren't immutable anymore anyway.
That's incorrect!

Anyways, giving you with GetEntries() []*ACLEntry on the ACL struct. With that you should be able to perform your sync operation.

@fabix
Copy link
Author

fabix commented Jan 16, 2026

I'd thought about adding this method as well, it could do the stuff if creating an ACL from scratch was possible (problem with version attribute that is only set by Load()). However it's also useful to get the entries in a manipulable form: for example, when allowing some users to access to a directory containing files/directories, it's convenient to just add x permission on directories if there a r permission exists. The only way to get the permissions of an ACLEntry is using PermUintToString() but NewEntry takes an uint16 as argument. In any case, all the attributes of an entry can be useful for a treatment and a string form is not efficient if you have to convert it back.

@steiler
Copy link
Owner

steiler commented Jan 16, 2026

You are right about the version attribute. I'm adding this:

// NewACL returns a new ACL instance
func NewACL() *ACL {
	return &ACL{
		version: 2,
		entries: []*ACLEntry{},
	}
}

You are perfectly right, the perm was not accessable at all. I'm hence also adding getters.
Further, what you can now do is this:

// Ensure user has read+execute but not write
newEntry := entry.WithPerm(PermRead | PermExecute).WithoutPerm(PermWrite)
acl.AddEntry(newEntry)

This takes the existing AclEntry, adds the Perms (that you can combine via the binary OR) and returns a new AclEntry instance. That you can then add to the ACL, which results in a replace of perms for the tag/id combination.

@fabix
Copy link
Author

fabix commented Jan 16, 2026

I think the new methods should be sufficient to do what I need, thanks.
However, in ACL.Equal() I'd added sorts because the order of the entries is undetermined (e.g. if the ACL has been built manually).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants