Bring the i386 linux mmap code more into line with how linux (2.4.x)

behaves. This fixes a lot of test which failed before. For amd64 there
are still some problems, but without any testers which apply patches
and run some predefines tests we can't do more ATM.

Submitted by:	Marcin Cieslak <saper@SYSTEM.PL> (minor fixups by myself)
Tested with:	LTP
This commit is contained in:
netchild 2006-09-20 17:24:20 +00:00
parent 4619fa3a87
commit 9f4eed62b7

View File

@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@ -598,9 +600,20 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
off_t pos;
} */ bsd_args;
int error;
struct file *fp;
error = 0;
bsd_args.flags = 0;
fp = NULL;
/*
* Linux mmap(2):
* You must specify exactly one of MAP_SHARED and MAP_PRIVATE
*/
if (! ((linux_args->flags & LINUX_MAP_SHARED) ^
(linux_args->flags & LINUX_MAP_PRIVATE)))
return EINVAL;
if (linux_args->flags & LINUX_MAP_SHARED)
bsd_args.flags |= MAP_SHARED;
if (linux_args->flags & LINUX_MAP_PRIVATE)
@ -681,11 +694,38 @@ linux_mmap_common(struct thread *td, struct l_mmap_argv *linux_args)
bsd_args.len = linux_args->len;
}
bsd_args.prot = linux_args->prot | PROT_READ; /* always required */
bsd_args.prot = linux_args->prot;
if (linux_args->flags & LINUX_MAP_ANON)
bsd_args.fd = -1;
else
else {
/*
* Linux follows Solaris mmap(2) description:
* The file descriptor fildes is opened with
* read permission, regardless of the
* protection options specified.
* If PROT_WRITE is specified, the application
* must have opened the file descriptor
* fildes with write permission unless
* MAP_PRIVATE is specified in the flag
* argument as described below.
*/
if ((error = fget(td, linux_args->fd, &fp)) != 0)
return error;
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
return EINVAL;
}
/* Linux mmap() just fails for O_WRONLY files */
if (! (fp->f_flag & FREAD)) {
fdrop(fp, td);
return EACCES;
}
bsd_args.fd = linux_args->fd;
fdrop(fp, td);
}
bsd_args.pos = linux_args->pos;
bsd_args.pad = 0;