aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/gamma-linux-drm.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/src/lib/gamma-linux-drm.c b/src/lib/gamma-linux-drm.c
index f6a4776..9d83038 100644
--- a/src/lib/gamma-linux-drm.c
+++ b/src/lib/gamma-linux-drm.c
@@ -191,44 +191,56 @@ int libgamma_linux_drm_site_restore(libgamma_site_state_t* restrict this)
*/
static int figure_out_card_open_error(const char* pathname)
{
+ /* Check which the device exists. */
if ((errno == ENXIO) || (errno == ENODEV))
return LIBGAMMA_NO_SUCH_PARTITION;
+ /* If we did not get access permission, figure out why. */
if (errno == EACCES)
{
+#define __test(R, W) ((attr.st_mode & (R | W)) == (R | W))
gid_t supplemental_groups[NGROUPS_MAX];
struct group* group;
- int i, n;
struct stat attr;
- int r;
-
+ int i, n;
- r = stat(pathname, &attr);
-#define __test(R, W) ((attr.st_mode & (R | W)) == (R | W))
- if (r)
+ /* Get permission requirement for the file. */
+ if (stat(pathname, &attr) < 0)
return errno == EACCES ? LIBGAMMA_NO_SUCH_PARTITION : LIBGAMMA_ERRNO_SET;
+ /* Test owner's, group's and others' permissions. */
if ((attr.st_uid == geteuid() && __test(S_IRUSR, S_IWUSR)) ||
(attr.st_gid == getegid() && __test(S_IRGRP, S_IWGRP)) ||
__test(S_IROTH, S_IWOTH))
return LIBGAMMA_DEVICE_ACCESS_FAILED;
+ /* The group should be "video", but perhaps
+ it is "root" to restrict users. */
if (attr.st_gid == 0 /* root group */ || __test(S_IRGRP, S_IWGRP))
return LIBGAMMA_DEVICE_RESTRICTED;
- n = getgroups(NGROUPS_MAX, supplemental_groups);
- if (n < 0)
+ /* Get the user's supplemental group membership list. */
+ if ((n = getgroups(NGROUPS_MAX, supplemental_groups)) < 0)
return LIBGAMMA_ERRNO_SET;
+ /* Test whether any of the supplemental
+ group should be satisfactory. */
for (i = 0; i < n; i++)
if (supplemental_groups[i] == attr.st_gid)
break;
+ /* If one of the supplemental groups
+ should be satisfactory, then we
+ do not know anything more than
+ that access failed. */
if (i != n)
return LIBGAMMA_DEVICE_ACCESS_FAILED;
+ /* Otherwise, try to get the name of
+ the group that is required and
+ report the missing group membership. */
errno = 0;
group = getgrgid(attr.st_gid); /* TODO: Not thread-safe. */
libgamma_group_gid = attr.st_gid;
@@ -237,6 +249,9 @@ static int figure_out_card_open_error(const char* pathname)
#undef __test
}
+ /* If we could not figure out what
+ went wrong, just return the error
+ we got. */
return LIBGAMMA_ERRNO_SET;
}