diff --git a/sycl/test/tools/Inputs/mock_renderd_access.c b/sycl/test/tools/Inputs/mock_renderd_access.c index 66cc41fea8bc4..86ddd475548d5 100644 --- a/sycl/test/tools/Inputs/mock_renderd_access.c +++ b/sycl/test/tools/Inputs/mock_renderd_access.c @@ -1,36 +1,57 @@ #define _GNU_SOURCE #include +#include #include #include #include -#include -int stat(const char *pathname, struct stat *statbuf) { - const char *mock_mode = getenv("MOCK_STAT_MODE"); - if (strstr(pathname, "renderD128")) { - if (mock_mode && strcmp(mock_mode, "notfound") == 0) { - errno = ENOENT; - return -1; - } - if (mock_mode && strcmp(mock_mode, "exists") == 0) { - memset(statbuf, 0, sizeof(*statbuf)); - statbuf->st_mode = S_IFCHR | 0666; - return 0; +int glob(const char *pattern, int flags, int (*errfunc)(const char *, int), + glob_t *pglob) { + const char *mock_mode = getenv("MOCK_GLOB_MODE"); + if (mock_mode && strcmp(mock_mode, "exists") == 0) { + // Simulate that /dev/dri/renderD* exists + pglob->gl_pathc = 2; + pglob->gl_pathv = malloc(2 * sizeof(char *)); + pglob->gl_pathv[0] = strdup("/dev/dri/renderD128"); + pglob->gl_pathv[1] = strdup("/dev/dri/renderD129"); + return 0; + } + // Default behavior: no matches + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + return 0; +} + +void globfree(glob_t *pglob) { + if (pglob->gl_pathv) { + for (size_t i = 0; i < pglob->gl_pathc; ++i) { + free(pglob->gl_pathv[i]); } + free(pglob->gl_pathv); + pglob->gl_pathv = NULL; + pglob->gl_pathc = 0; } - // Default: file does not exist - errno = ENOENT; - return -1; } int open(const char *pathname, int flags, ...) { const char *mock_mode = getenv("MOCK_OPEN_MODE"); - if (strstr(pathname, "renderD128")) { + if (strstr(pathname, "renderD12")) { if (mock_mode && strcmp(mock_mode, "deny") == 0) { errno = EACCES; return -1; } + + if (mock_mode && strcmp(mock_mode, "deny_second") == 0) { + // Simulate that the second file is not accessible + if (strstr(pathname, "renderD129")) { + errno = EACCES; + return -1; + } else { + return 3; + } + } + if (mock_mode && strcmp(mock_mode, "allow") == 0) { return 3; // Dummy fd } @@ -39,3 +60,5 @@ int open(const char *pathname, int flags, ...) { errno = EACCES; return -1; } + +int close(int fd) { return 0; } diff --git a/sycl/test/tools/render-group.cpp b/sycl/test/tools/render-group.cpp index 0a26d09306f69..17d7a8bb2e710 100644 --- a/sycl/test/tools/render-group.cpp +++ b/sycl/test/tools/render-group.cpp @@ -4,18 +4,27 @@ // LD_PRELOAD to mock the stat and open functions. // RUN: %clang -shared -fPIC -o %t-mock_stat.so %S/Inputs/mock_renderd_access.c -// Check the case when /dev/dri/renderD128 does not exist. -// RUN: env MOCK_STAT_MODE=notfound LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s -check-prefix=CHECK-NOTFOUND +// Check the case when /dev/dri/renderD12* don't exist. +// RUN: env MOCK_GLOB_MODE=notfound LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s -check-prefix=CHECK-NOTFOUND // We don't expect any warning about permissions in this case. -// CHECK-NOTFOUND-NOT: WARNING: Unable to access /dev/dri/renderD128 due to permissions (EACCES). +// CHECK-NOTFOUND-NOT: WARNING: Unable to access /dev/dri/renderD12 -// Check the case when /dev/dri/renderD128 exists but is not accessible. -// RUN: env MOCK_STAT_MODE=exists MOCK_OPEN_MODE=deny LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s --check-prefix=CHECK-DENY +// Check the case when /dev/dri/renderD12* exist but not accessible. +// RUN: env MOCK_GLOB_MODE=exists MOCK_OPEN_MODE=deny LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s --check-prefix=CHECK-DENY // CHECK-DENY: WARNING: Unable to access /dev/dri/renderD128 due to permissions (EACCES). // CHECK-DENY-NEXT: You might be missing the 'render' group locally. // CHECK-DENY-NEXT: Try: sudo usermod -a -G render $USER // CHECK-DENY-NEXT: Then log out and log back in. -// Check the case when /dev/dri/renderD128 exists and is accessible. -// RUN: env MOCK_STAT_MODE=exists MOCK_OPEN_MODE=allow LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s --check-prefix=CHECK-GRANT -// CHECK-GRANT-NOT: WARNING: Unable to access /dev/dri/renderD128 due to permissions (EACCES). +// Check the case when /dev/dri/renderD12* exist but only the first one is +// accessible. +// RUN: env MOCK_GLOB_MODE=exists MOCK_OPEN_MODE=deny_second LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s --check-prefix=CHECK-DENY-SECOND +// CHECK-DENY-SECOND-NOT: WARNING: Unable to access /dev/dri/renderD128 due to permissions (EACCES). +// CHECK-DENY-SECOND: WARNING: Unable to access /dev/dri/renderD129 due to permissions (EACCES). +// CHECK-DENY-SECOND-NEXT: You might be missing the 'render' group locally. +// CHECK-DENY-SECOND-NEXT: Try: sudo usermod -a -G render $USER +// CHECK-DENY-SECOND-NEXT: Then log out and log back in. + +// Check the case when /dev/dri/renderD12* exist and is accessible. +// RUN: env MOCK_GLOB_MODE=exists MOCK_OPEN_MODE=allow LD_PRELOAD=%t-mock_stat.so sycl-ls --verbose --ignore-device-selectors 2>&1 | FileCheck %s --check-prefix=CHECK-GRANT +// CHECK-GRANT-NOT: WARNING: Unable to access /dev/dri/renderD12 diff --git a/sycl/tools/sycl-ls/sycl-ls.cpp b/sycl/tools/sycl-ls/sycl-ls.cpp index 202e7b7e1c219..a1d22d83d32b8 100644 --- a/sycl/tools/sycl-ls/sycl-ls.cpp +++ b/sycl/tools/sycl-ls/sycl-ls.cpp @@ -29,7 +29,7 @@ #ifdef __linux__ #include #include -#include +#include #include #include #endif @@ -353,24 +353,24 @@ static int unsetFilterEnvVarsAndFork() { static void checkRenderGroupPermission() { #ifdef __linux__ - // Check for /dev/dri/render* devices - for (int i = 128; i < 256; ++i) { - std::string path = std::string("/dev/dri/renderD") + std::to_string(i); - struct stat st; - if (stat(path.c_str(), &st) == 0) { - int fd = open(path.c_str(), O_RDWR); - if (fd < 0 && errno == EACCES) { - std::cerr << "WARNING: Unable to access " << path - << " due to permissions (EACCES).\n" - << "You might be missing the 'render' group locally.\n" - << "Try: sudo usermod -a -G render $USER\n" - << "Then log out and log back in.\n"; - break; - } - if (fd >= 0) - close(fd); + glob_t glob_result; + glob("/dev/dri/renderD*", 0, nullptr, &glob_result); + for (size_t i = 0; i < glob_result.gl_pathc; ++i) { + const char *path = glob_result.gl_pathv[i]; + int fd = open(path, O_RDWR); + if (fd < 0 && errno == EACCES) { + std::cerr << "WARNING: Unable to access " << path + << " due to permissions (EACCES).\n" + << "You might be missing the 'render' group locally.\n" + << "Try: sudo usermod -a -G render $USER\n" + << "Then log out and log back in.\n"; + globfree(&glob_result); + break; } + if (fd >= 0) + close(fd); } + globfree(&glob_result); #endif }