/** Encode the ACL to the given buffer */
  private static void encode(List<AclEntry> acl, long address) {
    long offset = address;
    for (AclEntry ace : acl) {
      int flags = 0;

      // map UserPrincipal to uid and flags
      UserPrincipal who = ace.principal();
      if (!(who instanceof UnixUserPrincipals.User)) throw new ProviderMismatchException();
      UnixUserPrincipals.User user = (UnixUserPrincipals.User) who;
      int uid;
      if (user.isSpecial()) {
        uid = -1;
        if (who == UnixUserPrincipals.SPECIAL_OWNER) flags |= ACE_OWNER;
        else if (who == UnixUserPrincipals.SPECIAL_GROUP)
          flags |= (ACE_GROUP | ACE_IDENTIFIER_GROUP);
        else if (who == UnixUserPrincipals.SPECIAL_EVERYONE) flags |= ACE_EVERYONE;
        else throw new AssertionError("Unable to map special identifier");
      } else {
        if (user instanceof UnixUserPrincipals.Group) {
          uid = user.gid();
          flags |= ACE_IDENTIFIER_GROUP;
        } else {
          uid = user.uid();
        }
      }

      // map ACE type
      int type;
      switch (ace.type()) {
        case ALLOW:
          type = ACE_ACCESS_ALLOWED_ACE_TYPE;
          break;
        case DENY:
          type = ACE_ACCESS_DENIED_ACE_TYPE;
          break;
        case AUDIT:
          type = ACE_SYSTEM_AUDIT_ACE_TYPE;
          break;
        case ALARM:
          type = ACE_SYSTEM_ALARM_ACE_TYPE;
          break;
        default:
          throw new AssertionError("Unable to map ACE type");
      }

      // map permissions
      Set<AclEntryPermission> aceMask = ace.permissions();
      int mask = 0;
      if (aceMask.contains(AclEntryPermission.READ_DATA)) mask |= ACE_READ_DATA;
      if (aceMask.contains(AclEntryPermission.WRITE_DATA)) mask |= ACE_WRITE_DATA;
      if (aceMask.contains(AclEntryPermission.APPEND_DATA)) mask |= ACE_APPEND_DATA;
      if (aceMask.contains(AclEntryPermission.READ_NAMED_ATTRS)) mask |= ACE_READ_NAMED_ATTRS;
      if (aceMask.contains(AclEntryPermission.WRITE_NAMED_ATTRS)) mask |= ACE_WRITE_NAMED_ATTRS;
      if (aceMask.contains(AclEntryPermission.EXECUTE)) mask |= ACE_EXECUTE;
      if (aceMask.contains(AclEntryPermission.DELETE_CHILD)) mask |= ACE_DELETE_CHILD;
      if (aceMask.contains(AclEntryPermission.READ_ATTRIBUTES)) mask |= ACE_READ_ATTRIBUTES;
      if (aceMask.contains(AclEntryPermission.WRITE_ATTRIBUTES)) mask |= ACE_WRITE_ATTRIBUTES;
      if (aceMask.contains(AclEntryPermission.DELETE)) mask |= ACE_DELETE;
      if (aceMask.contains(AclEntryPermission.READ_ACL)) mask |= ACE_READ_ACL;
      if (aceMask.contains(AclEntryPermission.WRITE_ACL)) mask |= ACE_WRITE_ACL;
      if (aceMask.contains(AclEntryPermission.WRITE_OWNER)) mask |= ACE_WRITE_OWNER;
      if (aceMask.contains(AclEntryPermission.SYNCHRONIZE)) mask |= ACE_SYNCHRONIZE;

      // FIXME - it would be desirable to know here if the file is a
      // directory or not. Solaris returns EINVAL if an ACE has a directory
      // -only flag and the file is not a directory.
      Set<AclEntryFlag> aceFlags = ace.flags();
      if (aceFlags.contains(AclEntryFlag.FILE_INHERIT)) flags |= ACE_FILE_INHERIT_ACE;
      if (aceFlags.contains(AclEntryFlag.DIRECTORY_INHERIT)) flags |= ACE_DIRECTORY_INHERIT_ACE;
      if (aceFlags.contains(AclEntryFlag.NO_PROPAGATE_INHERIT))
        flags |= ACE_NO_PROPAGATE_INHERIT_ACE;
      if (aceFlags.contains(AclEntryFlag.INHERIT_ONLY)) flags |= ACE_INHERIT_ONLY_ACE;

      unsafe.putInt(offset + OFFSETOF_UID, uid);
      unsafe.putInt(offset + OFFSETOF_MASK, mask);
      unsafe.putShort(offset + OFFSETOF_FLAGS, (short) flags);
      unsafe.putShort(offset + OFFSETOF_TYPE, (short) type);

      offset += SIZEOF_ACE_T;
    }
  }