MFC (4 of X):
- don't limit number of syscalls to 255 - handle more socket options - bug-/compatibility-fixes to linux * file related (includes fixes which prevent creation of strange files which can only be removed with a fsck) * make ping work * ... - add devfs to the file system type handling/translation Compile tested by: scf (i386, as part of a mega-MFC-patch) Tested by: Arno J. Klaassen <arno@heho.snv.jussieu.fr> (amd64)
This commit is contained in:
parent
47a37c3274
commit
962e1e6836
@ -974,7 +974,7 @@ linux32_fixlimit(struct rlimit *rl, int which)
|
||||
struct sysentvec elf_linux_sysvec = {
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
0,
|
||||
LINUX_SIGTBLSZ,
|
||||
bsd_to_linux_signal,
|
||||
ELAST + 1,
|
||||
|
@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/tty.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
@ -268,7 +269,17 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
|
||||
struct l_dirent64 linux_dirent64;
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
u_long *cookies = NULL, *cookiep;
|
||||
int ncookies;
|
||||
int ncookies, vfslocked;
|
||||
|
||||
nbytes = args->count;
|
||||
if (nbytes == 1) {
|
||||
/* readdir(2) case. Always struct dirent. */
|
||||
if (is64bit)
|
||||
return (EINVAL);
|
||||
nbytes = sizeof(linux_dirent);
|
||||
justone = 1;
|
||||
} else
|
||||
justone = 0;
|
||||
|
||||
if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
|
||||
return (error);
|
||||
@ -279,23 +290,13 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
|
||||
}
|
||||
|
||||
vp = fp->f_vnode;
|
||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||
if (vp->v_type != VDIR) {
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
fdrop(fp, td);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
nbytes = args->count;
|
||||
if (nbytes == 1) {
|
||||
/* readdir(2) case. Always struct dirent. */
|
||||
if (is64bit) {
|
||||
fdrop(fp, td);
|
||||
return (EINVAL);
|
||||
}
|
||||
nbytes = sizeof(linux_dirent);
|
||||
justone = 1;
|
||||
} else
|
||||
justone = 0;
|
||||
|
||||
off = fp->f_offset;
|
||||
|
||||
buflen = max(LINUX_DIRBLKSIZ, nbytes);
|
||||
@ -448,6 +449,7 @@ out:
|
||||
free(cookies, M_TEMP);
|
||||
|
||||
VOP_UNLOCK(vp, 0, td);
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
fdrop(fp, td);
|
||||
free(buf, M_TEMP);
|
||||
return (error);
|
||||
@ -487,6 +489,10 @@ linux_access(struct thread *td, struct linux_access_args *args)
|
||||
char *path;
|
||||
int error;
|
||||
|
||||
/* linux convention */
|
||||
if (args->flags & ~(F_OK | X_OK | W_OK | R_OK))
|
||||
return (EINVAL);
|
||||
|
||||
LCONVPATHEXIST(td, args->path, &path);
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -719,12 +725,28 @@ linux_pread(td, uap)
|
||||
struct linux_pread_args *uap;
|
||||
{
|
||||
struct pread_args bsd;
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
bsd.fd = uap->fd;
|
||||
bsd.buf = uap->buf;
|
||||
bsd.nbyte = uap->nbyte;
|
||||
bsd.offset = uap->offset;
|
||||
return pread(td, &bsd);
|
||||
|
||||
error = pread(td, &bsd);
|
||||
|
||||
if (error == 0) {
|
||||
/* This seems to violate POSIX but linux does it */
|
||||
if ((error = fgetvp(td, uap->fd, &vp)) != 0)
|
||||
return (error);
|
||||
if (vp->v_type == VDIR) {
|
||||
vrele(vp);
|
||||
return (EISDIR);
|
||||
}
|
||||
vrele(vp);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -812,6 +812,12 @@ linux_waitpid(struct thread *td, struct linux_waitpid_args *args)
|
||||
printf(ARGS(waitpid, "%d, %p, %d"),
|
||||
args->pid, (void *)args->status, args->options);
|
||||
#endif
|
||||
/*
|
||||
* this is necessary because the test in kern_wait doesn't work
|
||||
* because we mess with the options here
|
||||
*/
|
||||
if (args->options & ~(WUNTRACED | WNOHANG | WCONTINUED | __WCLONE))
|
||||
return (EINVAL);
|
||||
|
||||
options = (args->options & (WNOHANG | WUNTRACED));
|
||||
/* WLINUXCLONE should be equal to __WCLONE, but we make sure */
|
||||
@ -898,11 +904,34 @@ linux_mknod(struct thread *td, struct linux_mknod_args *args)
|
||||
printf(ARGS(mknod, "%s, %d, %d"), path, args->mode, args->dev);
|
||||
#endif
|
||||
|
||||
if (args->mode & S_IFIFO)
|
||||
switch (args->mode & S_IFMT) {
|
||||
case S_IFIFO:
|
||||
case S_IFSOCK:
|
||||
error = kern_mkfifo(td, path, UIO_SYSSPACE, args->mode);
|
||||
else
|
||||
break;
|
||||
|
||||
case S_IFCHR:
|
||||
case S_IFBLK:
|
||||
error = kern_mknod(td, path, UIO_SYSSPACE, args->mode,
|
||||
args->dev);
|
||||
break;
|
||||
|
||||
case S_IFDIR:
|
||||
error = EPERM;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
args->mode |= S_IFREG;
|
||||
/* FALLTHROUGH */
|
||||
case S_IFREG:
|
||||
error = kern_open(td, path, UIO_SYSSPACE,
|
||||
O_WRONLY | O_CREAT | O_TRUNC, args->mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
LFREEPATH(path);
|
||||
return (error);
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
@ -299,6 +300,20 @@ linux_to_bsd_so_sockopt(int opt)
|
||||
return (SO_OOBINLINE);
|
||||
case LINUX_SO_LINGER:
|
||||
return (SO_LINGER);
|
||||
case LINUX_SO_PEERCRED:
|
||||
return (LOCAL_PEERCRED);
|
||||
case LINUX_SO_RCVLOWAT:
|
||||
return (SO_RCVLOWAT);
|
||||
case LINUX_SO_SNDLOWAT:
|
||||
return (SO_SNDLOWAT);
|
||||
case LINUX_SO_RCVTIMEO:
|
||||
return (SO_RCVTIMEO);
|
||||
case LINUX_SO_SNDTIMEO:
|
||||
return (SO_SNDTIMEO);
|
||||
case LINUX_SO_TIMESTAMP:
|
||||
return (SO_TIMESTAMP);
|
||||
case LINUX_SO_ACCEPTCONN:
|
||||
return (SO_ACCEPTCONN);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
@ -924,11 +939,15 @@ linux_recvfrom(struct thread *td, struct linux_recvfrom_args *args)
|
||||
struct sockaddr * __restrict from;
|
||||
socklen_t * __restrict fromlenaddr;
|
||||
} */ bsd_args;
|
||||
size_t len;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(args, &linux_args, sizeof(linux_args))))
|
||||
return (error);
|
||||
|
||||
if ((error = copyin(PTRIN(linux_args.fromlen), &len, sizeof(size_t))))
|
||||
return (error);
|
||||
|
||||
bsd_args.s = linux_args.s;
|
||||
bsd_args.buf = PTRIN(linux_args.buf);
|
||||
bsd_args.len = linux_args.len;
|
||||
@ -970,6 +989,16 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args)
|
||||
error = copyin(PTRIN(linux_args.msg), &msg, sizeof(msg));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Some Linux applications (ping) define a non-NULL control data
|
||||
* pointer, but a msg_controllen of 0, which is not allowed in the
|
||||
* FreeBSD system call interface. NULL the msg_control pointer in
|
||||
* order to handle this case. This should be checked, but allows the
|
||||
* Linux ping to work.
|
||||
*/
|
||||
if (msg.msg_control != NULL && msg.msg_controllen == 0)
|
||||
msg.msg_control = NULL;
|
||||
error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE);
|
||||
if (error)
|
||||
return (error);
|
||||
|
@ -211,7 +211,8 @@ linux_newlstat(struct thread *td, struct linux_newlstat_args *args)
|
||||
#endif
|
||||
|
||||
error = kern_lstat(td, path, UIO_SYSSPACE, &sb);
|
||||
translate_path_major_minor(td, path, &sb);
|
||||
if (!error)
|
||||
translate_path_major_minor(td, path, &sb);
|
||||
LFREEPATH(path);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -261,6 +262,7 @@ struct l_statfs {
|
||||
#define LINUX_NTFS_SUPER_MAGIC 0x5346544EL
|
||||
#define LINUX_PROC_SUPER_MAGIC 0x9fa0L
|
||||
#define LINUX_UFS_SUPER_MAGIC 0x00011954L /* XXX - UFS_MAGIC in Linux */
|
||||
#define LINUX_DEVFS_SUPER_MAGIC 0x1373L
|
||||
|
||||
static long
|
||||
bsd_to_linux_ftype(const char *fstypename)
|
||||
@ -277,6 +279,7 @@ bsd_to_linux_ftype(const char *fstypename)
|
||||
{"nwfs", LINUX_NCP_SUPER_MAGIC},
|
||||
{"hpfs", LINUX_HPFS_SUPER_MAGIC},
|
||||
{"coda", LINUX_CODA_SUPER_MAGIC},
|
||||
{"devfs", LINUX_DEVFS_SUPER_MAGIC},
|
||||
{NULL, 0L}};
|
||||
|
||||
for (i = 0; b2l_tbl[i].bsd_name != NULL; i++)
|
||||
@ -409,18 +412,19 @@ linux_stat64(struct thread *td, struct linux_stat64_args *args)
|
||||
#endif
|
||||
|
||||
error = kern_stat(td, filename, UIO_SYSSPACE, &buf);
|
||||
if (!error && strlen(filename) > strlen("/dev/pts/") &&
|
||||
!strncmp(filename, "/dev/pts/", strlen("/dev/pts/"))
|
||||
&& filename[9] >= '0' && filename[9] <= '9') {
|
||||
/*
|
||||
* Linux checks major and minors of the slave device to make
|
||||
* sure it's a pty deivce, so let's make him believe it is.
|
||||
*/
|
||||
buf.st_rdev = (136 << 8);
|
||||
if (!error) {
|
||||
if (strlen(filename) > strlen("/dev/pts/") &&
|
||||
!strncmp(filename, "/dev/pts/", strlen("/dev/pts/")) &&
|
||||
filename[9] >= '0' && filename[9] <= '9') {
|
||||
/*
|
||||
* Linux checks major and minors of the slave device
|
||||
* to make sure it's a pty deivce, so let's make him
|
||||
* believe it is.
|
||||
*/
|
||||
buf.st_rdev = (136 << 8);
|
||||
} else
|
||||
translate_path_major_minor(td, filename, &buf);
|
||||
}
|
||||
|
||||
translate_path_major_minor(td, filename, &buf);
|
||||
|
||||
LFREEPATH(filename);
|
||||
if (error)
|
||||
return (error);
|
||||
@ -442,7 +446,8 @@ linux_lstat64(struct thread *td, struct linux_lstat64_args *args)
|
||||
#endif
|
||||
|
||||
error = kern_lstat(td, filename, UIO_SYSSPACE, &sb);
|
||||
translate_path_major_minor(td, filename, &sb);
|
||||
if (!error)
|
||||
translate_path_major_minor(td, filename, &sb);
|
||||
LFREEPATH(filename);
|
||||
if (error)
|
||||
return (error);
|
||||
|
@ -797,7 +797,7 @@ exec_linux_setregs(struct thread *td, u_long entry,
|
||||
struct sysentvec linux_sysvec = {
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
0,
|
||||
LINUX_SIGTBLSZ,
|
||||
bsd_to_linux_signal,
|
||||
ELAST + 1,
|
||||
@ -826,7 +826,7 @@ struct sysentvec linux_sysvec = {
|
||||
struct sysentvec elf_linux_sysvec = {
|
||||
LINUX_SYS_MAXSYSCALL,
|
||||
linux_sysent,
|
||||
0xff,
|
||||
0,
|
||||
LINUX_SIGTBLSZ,
|
||||
bsd_to_linux_signal,
|
||||
ELAST + 1,
|
||||
|
Loading…
x
Reference in New Issue
Block a user