munmap_exe.stderr.exp munmap_exe.vgtest \
nestedfns.stderr.exp nestedfns.stdout.exp nestedfns.vgtest \
pending.stdout.exp pending.stderr.exp pending.vgtest \
+ procfs-linux.stderr.exp procfs-linux.vgtest \
+ procfs-non-linux.stderr.exp procfs-non-linux.vgtest \
pth_atfork1.stderr.exp pth_atfork1.stdout.exp pth_atfork1.vgtest \
pth_blockedsig.stderr.exp \
pth_blockedsig.stdout.exp pth_blockedsig.vgtest \
munmap_exe map_unaligned map_unmap mq \
nestedfns \
pending \
+ procfs-cmdline-exe \
pth_atfork1 pth_blockedsig pth_cancel1 pth_cancel2 pth_cvsimple \
pth_empty pth_exit pth_exit2 pth_mutexspeed pth_once pth_rwlock \
pth_stackalign \
--- /dev/null
+/*
+ * Read /proc/self/cmdline and /proc/self/exe such that it can be tested
+ * whether Valgrind intercepts the system calls that access these pseudo-files
+ * properly on Linux and whether Valgrind does not modify the behavior of
+ * accessing these files on other operating systems.
+ */
+
+#define _ATFILE_SOURCE
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include "../../config.h"
+
+static void test_cmdline(const char* const cwd, const char* const label,
+ const char* const path)
+{
+ int fd, n;
+ char ch;
+
+ fprintf(stderr, "%s:\n", label);
+ fd = open(path, 0);
+ if (fd >= 0)
+ {
+ while ((n = read(fd, &ch, 1)) > 0)
+ {
+ if (ch == '\\')
+ fprintf(stderr, "\\\\");
+ else if (ch == 0)
+ fprintf(stderr, "\\0");
+ else if (isprint((unsigned)ch))
+ fprintf(stderr, "%c", ch);
+ else
+ fprintf(stderr, "\\0%o", ch);
+ }
+ fprintf(stderr, "\n");
+ close(fd);
+ }
+ else
+ perror("open()");
+}
+
+static void test_readlink(const char* const cwd, const char* const label,
+ const char* const path)
+{
+ char buf[512];
+ const char* p;
+ int n;
+
+ if ((n = readlink(path, buf, sizeof(buf) - 1)) >= 0)
+ {
+ buf[n] = 0;
+ p = buf;
+ if (strncmp(buf, cwd, strlen(cwd)) == 0)
+ p += strlen(cwd);
+ fprintf(stderr, "Result of readlink(\"%s\"): %s\n", label, p);
+ }
+ else
+ perror("readlink");
+}
+
+static void test_readlinkat(const char* const cwd, const char* const label,
+ const char* const path)
+{
+#if HAVE_READLINKAT
+ char buf[512];
+ const char* p;
+ int n;
+
+ if ((n = readlinkat(AT_FDCWD, path, buf, sizeof(buf) - 1)) >= 0)
+ {
+ buf[n] = 0;
+ p = buf;
+ if (strncmp(buf, cwd, strlen(cwd)) == 0)
+ p += strlen(cwd);
+ fprintf(stderr, "Result of readlinkat(\"%s\"): %s\n", label, p);
+ }
+ else
+ perror("readlinkat");
+#else
+ errno = ENOSYS;
+ perror("readlinkat");
+#endif
+}
+
+int main(int argc, char** argv)
+{
+ char cwd[512];
+ char path[512];
+
+ cwd[0] = 0;
+ if (! getcwd(cwd, sizeof(cwd)))
+ perror("getcwd");
+ strcat(cwd, "/");
+
+ snprintf(path, sizeof(path), "/proc/%d/cmdline", getpid());
+
+ test_cmdline(cwd, "/proc/self/cmdline", "/proc/self/cmdline");
+ test_cmdline(cwd, "/proc/<pid>/cmdline", path);
+
+ snprintf(path, sizeof(path), "/proc/%d/exe", getpid());
+
+ test_readlink(cwd, "/proc/self/exe", "/proc/self/exe");
+ test_readlink(cwd, "/proc/<pid>/exe", path);
+
+ test_readlinkat(cwd, "/proc/self/exe", "/proc/self/exe");
+ test_readlinkat(cwd, "/proc/<pid>/exe", path);
+
+ return 0;
+}