mmap/mmap_tests.c
/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following functions.
- sigquit
- sigalrm
- sigsegv
- test_child
- main
/* $Id: mmap_tests.c,v 1.2 2002/03/24 13:24:23 proff Exp $
*
* various mmap() implimentations suck; we attempt to find out just how
* hard.
*
* - Julian Assange (proff@iq.org)
*
* Test results: (please send additions to proff@iq.org)
*
* linux 2.0.0 allows shared mmaps only for files, while 1.2.13
* doesn't permit shared mmaps at all.
*
* Linux suburbia 2.0.0 #29- Thu Jul 11 18:03:20 EST 1996 i586
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
*
* Linux server 1.2.13 #6 Wed Feb 28 15:45:11 CST 1996 i486 (forget it)
*
* program output:
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
*
* Freebsd is purrrrfect.
*
* FreeBSD profane 2.2-CURRENT #0 Sat Jul 27 19:16:00 EST 1996
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED
* HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
*
* Suprisingly, AIX is faultless too.
*
* AIX whisky 2 3 000027477600
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED
* HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
*
* Shared mmap file writes are screwed under BSDI!
*
* BSD/OS telepath.com 2.1 BSDI BSD/OS 2.1 Kernel #3: Thu Mar 7 10:47:49 CST 1996
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED
* HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
*
* SunOS omega.iqm.unicamp.br 5.4 generic i86pc i386
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
*
* SunOS chaos 4.1C 4.1.3 sun4
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
*
* SunOS unix1 5.3 Generic_101318-59 sun4m sparc (no shared file write?)
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
*
* SunOS sydney6 5.5 Generic_103093-03 sun4m sparc SUNW,SPARCstation-20
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
*
* Novell Unixware 2.03 (System V Release 4.2MP) UNIX_SV aapo 4.2MP 2.03 i386 x86at
*
* HAVE_MMAP_FILE_PRIVATE_READ
* HAVE_MMAP_FILE_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_FILE_PRIVATE_WRITE
* HAVE_MMAP_FILE_SHARED_READ
* HAVE_MMAP_FILE_SHARED_CHILD_INHERIT
* HAVE_MMAP_FILE_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_FILE_SHARED_PARENT_READ_CHILD_WRITE
* HAVE_MMAP_FILE_SHARED_WRITE
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_DEV_ZERO_SHARED_PARENT_READ_CHILD_WRITE
*
* ULTRIX wolf.cs.washington.edu 4.2 0 RISC (way to go ultrix)
*
* nothing. zilch.
*
* OSF1 porky-pig V3.2 214 alpha (unexpected. osf/1 sucks).
*
* HAVE_MMAP_DEV_ZERO_PRIVATE
* HAVE_MMAP_DEV_ZERO_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_DEV_ZERO_SHARED
* HAVE_MMAP_DEV_ZERO_SHARED_CHILD_INHERIT
* HAVE_MMAP_ANON_PRIVATE
* HAVE_MMAP_ANON_PRIVATE_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED
* HAVE_MMAP_ANON_SHARED_CHILD_INHERIT
* HAVE_MMAP_ANON_SHARED_CHILD_READ_PARENT_WRITE
* HAVE_MMAP_ANON_SHARED_PARENT_READ_CHILD_WRITE
*/
#include "config.h"
#ifdef HAVE_MMAP
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MM_SIZE (100*1024)
#define TEST_FILE "mmap_test.tmp"
#if SIZEOF_CHAR_P > 4
# define POINTER_FMT "0x%lx"
# define POINTER_CAST unsigned long int
#else
# define POINTER_FMT "0x%x"
# define POINTER_CAST unsigned int
#endif
int caught_sigquit;
void sigquit (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
caught_sigquit++;
signal (SIGQUIT, sigquit);
}
void sigalrm (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
caught_sigquit++;
signal (SIGALRM, sigalrm);
}
jmp_buf jmp;
void sigsegv (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
signal (SIGSEGV, sigsegv);
longjmp (jmp, 1);
}
/*
* TODO: test MAP_INHERIT, MAP_FIXED (can't see that latter being much of an issue)
*/
void
test_child(char *p, char *msg)
/* [<][>][^][v][top][bottom][index][help] */
{
char *im = "inherit_magic";
char *pm = "parent_magic";
char *cm = "child_magic";
pid_t pid;
int ws;
fflush (stdout);
if (!setjmp(jmp))
strcpy (p, im);
caught_sigquit = 0;
signal (SIGQUIT, sigquit);
signal (SIGCHLD, SIG_IGN);
signal (SIGALRM, sigalrm);
pid = fork();
if (pid<0)
return;
if (pid==0)
{
if (!setjmp(jmp))
if (strcmp(p, im)==0)
printf("%s_CHILD_INHERIT " POINTER_FMT "\n", msg, (POINTER_CAST)p);
alarm(5);
kill (getppid(), SIGQUIT);
while (!caught_sigquit)
pause ();
caught_sigquit = 0;
if (!setjmp(jmp))
if (strcmp(p, pm)==0)
printf("%s_CHILD_READ_PARENT_WRITE " POINTER_FMT "\n", msg, (POINTER_CAST)p);
if (!setjmp(jmp))
strcpy (p, cm);
fflush (stdout);
kill (getppid(), SIGQUIT);
exit(0);
}
/* parent */
alarm(5);
while (!caught_sigquit)
pause ();
caught_sigquit = 0;
if (!setjmp(jmp))
strcpy (p, pm);
alarm(5);
kill (pid, SIGQUIT);
while (!caught_sigquit)
pause ();
if (!setjmp(jmp))
if (strcmp(p, cm)==0)
printf("%s_PARENT_READ_CHILD_WRITE " POINTER_FMT "\n", msg, (POINTER_CAST)p);
signal (SIGQUIT, SIG_DFL);
alarm(0);
wait(&ws);
}
int
main()
/* [<][>][^][v][top][bottom][index][help] */
{
volatile int fd;
char *m = malloc(MM_SIZE);
char buf[1024];
signal (SIGSEGV, sigsegv);
#if defined(MAP_PRIVATE)
fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
strcpy (m, "mmap magic");
write (fd, m, MM_SIZE);
lseek (fd, 0, SEEK_SET);
if (fd>=0)
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
if (strcmp(p, m)==0)
printf("HAVE_MMAP_FILE_PRIVATE_READ " POINTER_FMT "\n", (POINTER_CAST)p);
test_child(p, "HAVE_MMAP_FILE_PRIVATE");
if (!setjmp(jmp))
{
write (fd, "mmap magic2", 12);
if (strcmp(p, "mmap magic2")==0) /* changes should be *private* */
printf("HAVE_MMAP_FILE_PRIVATE_BAD_MERGED_VM_BUFFER_CACHE " POINTER_FMT "\n", (POINTER_CAST)p);
}
if (!setjmp(jmp))
{
strcpy (p, "mmap magic3");
munmap (p, MM_SIZE);
lseek (fd, SEEK_SET, 0);
read (fd, buf, 12);
if (strcmp(buf, "mmap magic3")==0)
printf("HAVE_MMAP_FILE_PRIVATE_WRITE " POINTER_FMT "\n", (POINTER_CAST)p);
} else
munmap (p, MM_SIZE);
}
close (fd);
}
#endif
#if defined(MAP_SHARED)
fd = open(TEST_FILE, O_RDWR|O_CREAT|O_TRUNC, 0666);
strcpy (m, "mmap magic");
write (fd, m, MM_SIZE);
lseek (fd, 0, SEEK_SET);
if (fd>=0)
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
if (strcmp(p, m)==0)
printf("HAVE_MMAP_FILE_SHARED_READ " POINTER_FMT "\n", (POINTER_CAST)p);
test_child(p, "HAVE_MMAP_FILE_SHARED");
if (!setjmp(jmp))
{
write (fd, "mmap magic2", 12);
if (strcmp(p, "mmap magic2")==0)
printf("HAVE_MMAP_FILE_SHARED_MERGED_VM_BUFFER_CACHE " POINTER_FMT "\n", (POINTER_CAST)p);
}
if (!setjmp(jmp))
{
strcpy (p, "mmap magic3");
munmap (p, MM_SIZE);
lseek (fd, SEEK_SET, 0);
read (fd, buf, 12);
if (strcmp(buf, "mmap magic3")==0)
printf("HAVE_MMAP_FILE_SHARED_WRITE " POINTER_FMT "\n", (POINTER_CAST)p);
} else
munmap (p, MM_SIZE);
}
close (fd);
}
#endif
#if defined(MAP_PRIVATE)
fd = open("/dev/zero", O_RDWR, 0666);
if (fd>=0)
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
{
strcpy (p, "mmap magic_dev_zero");
if (strcmp (p, "mmap magic_dev_zero")==0)
printf("HAVE_MMAP_DEV_ZERO_PRIVATE " POINTER_FMT "\n", (POINTER_CAST)p);
}
test_child(p, "HAVE_MMAP_DEV_ZERO_PRIVATE");
munmap (p, MM_SIZE);
}
close (fd);
}
#endif
#if defined(MAP_PRIVATE)
fd = open("/dev/zero", O_RDWR, 0666);
if (fd>=0)
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
{
strcpy (p, "mmap magic_dev_zero_shared");
if (strcmp (p, "mmap magic_dev_zero_shared")==0)
printf("HAVE_MMAP_DEV_ZERO_SHARED " POINTER_FMT "\n", (POINTER_CAST)p);
}
test_child(p, "HAVE_MMAP_DEV_ZERO_SHARED");
munmap (p, MM_SIZE);
}
close (fd);
}
#endif
#if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
#define MAP_ANON MAP_ANONYMOUS
#endif
#ifdef MAP_ANON
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
{
strcpy (p, "mmap magic_anon");
if (strcmp(p, "mmap magic_anon")==0)
printf("HAVE_MMAP_ANON_PRIVATE " POINTER_FMT "\n", (POINTER_CAST)p);
}
test_child(p, "HAVE_MMAP_ANON_PRIVATE");
munmap (p, MM_SIZE);
}
}
#endif
#if defined(MAP_ANON) && defined(MAP_SHARED)
{
char *p=(char *)mmap(0, MM_SIZE, PROT_READ | PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
if (p!=(char *)-1)
{
if (!setjmp(jmp))
{
strcpy (p, "mmap magic_shared_anon");
if (strcmp(p, "mmap magic_shared_anon")==0)
printf("HAVE_MMAP_ANON_SHARED " POINTER_FMT "\n", (POINTER_CAST)p);
}
test_child(p, "HAVE_MMAP_ANON_SHARED");
munmap (p, MM_SIZE);
}
}
#endif
unlink(TEST_FILE);
exit (0);
}
#else /* HAVE_MMAP */
# error mmap, not even dentures.
#endif