diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/gamma-linux-drm.c | 31 |
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; } |