{
PRINT("access_extended( %#lx(%s), %lu, %#lx, %lu )",
ARG1, (char *)ARG1, ARG2, ARG3, ARG4);
+ // XXX: the accessx_descriptor struct contains padding, so this can cause
+ // unnecessary undefined value errors. But you arguably shouldn't be
+ // passing undefined values to the kernel anyway...
PRE_REG_READ4(int, "access_extended", void *, entries, vki_size_t, size,
vki_errno_t *, results, vki_uid_t *, uid);
PRE_MEM_READ("access_extended(entries)", ARG1, ARG2 );
// shortest possible string section. The shortest string section allowed
// consists of a single one-char string (plus the NUL char). Hence the
// '2'.
- struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG2;
+ struct vki_accessx_descriptor* entries = (struct vki_accessx_descriptor*)ARG1;
SizeT size = ARG2;
Int n_descs = (size - 2) / sizeof(struct accessx_descriptor);
- Int i = 0; // Current position in the descriptors section array.
+ Int i; // Current position in the descriptors section array.
Int u; // Upper bound on the length of the descriptors array
- // (recomputed each time around the loop)
+ // (recomputed each time around the loop)
vg_assert(n_descs > 0);
// Step through the descriptors, lowering 'n_descs' until we know we've
// reached the string section.
- while (True)
- {
+ for (i = 0; True; i++) {
// If we're past our estimate, we must be one past the end of the
// descriptors section (ie. at the start of the string section). Stop.
if (i >= n_descs)
dist_noinst_SCRIPTS = filter_stderr
EXTRA_DIST = \
+ access_extended.stderr.exp access_extended.vgtest \
apple-main-arg.stderr.exp apple-main-arg.vgtest \
rlimit.stderr.exp rlimit.vgtest
check_PROGRAMS = \
+ access_extended \
apple-main-arg \
rlimit
--- /dev/null
+// This is a test for access_extended(), one of the more ridiculous syscalls
+// ever devised. For bug 200760. See the comments on the wrapper in
+// syswrap-darwin.c to understand what is going on here.
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void)
+{
+ char* name1 = "access_extended.c";
+ char* name2 = "no_such_file";
+ // Space for three descriptors and the two strings (and NUL chars for them).
+ size_t entries_szB =
+ sizeof(struct accessx_descriptor) * 3 +
+ strlen(name1) + 1 +
+ strlen(name2) + 1;
+ struct accessx_descriptor* entries = malloc(entries_szB);
+ char* string1 = (char*)&entries[3];
+ char* string2 = string1 + strlen(name1) + 1;
+ int results[3];
+ int retval;
+
+ entries[0].ad_name_offset = string1 - (char*)entries;
+ entries[1].ad_name_offset = 0; // reuse the previous entry's string
+ entries[2].ad_name_offset = string2 - (char*)entries;
+ entries[0].ad_flags = F_OK; // succeeds
+ entries[1].ad_flags = X_OK; // fails
+ entries[2].ad_flags = F_OK; // fails
+ strcpy(string1, name1);
+ strcpy(string2, name2);
+
+ retval = syscall(SYS_access_extended, entries, entries_szB, results,
+ /*uid--unused?*/0);
+
+ fprintf(stderr, "retval = %d\n", retval);
+ fprintf(stderr, "%s(F_OK) = %d (%s)\n",
+ name1, results[0], strerror(results[0]));
+ fprintf(stderr, "%s(X_OK) = %d (%s)\n",
+ name1, results[1], strerror(results[1]));
+ fprintf(stderr, "%s(F_OK) = %d (%s)\n",
+ name2, results[2], strerror(results[2]));
+
+ return 0;
+}
+
--- /dev/null
+retval = 0
+access_extended.c(F_OK) = 0 (Unknown error: 0)
+access_extended.c(X_OK) = 13 (Permission denied)
+no_such_file(F_OK) = 2 (No such file or directory)
--- /dev/null
+prog: access_extended
+vgopts: -q