aboutsummaryrefslogtreecommitdiff
path: root/sys/compat
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1996-03-02 19:38:20 +0000
committerPeter Wemm <peter@FreeBSD.org>1996-03-02 19:38:20 +0000
commitd66a506616078adf4d266a309f979ffd95fe634f (patch)
tree83b4d342a731e2a76c19f214d574f24753abe420 /sys/compat
parent9a074e93b595e10edfd4c6fd6bdacc61879fe381 (diff)
Notes
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/linux/linux_file.c397
-rw-r--r--sys/compat/linux/linux_ioctl.c47
-rw-r--r--sys/compat/linux/linux_ipc.c54
-rw-r--r--sys/compat/linux/linux_misc.c433
-rw-r--r--sys/compat/linux/linux_signal.c210
-rw-r--r--sys/compat/linux/linux_socket.c9
-rw-r--r--sys/compat/linux/linux_stats.c161
-rw-r--r--sys/compat/linux/linux_util.c179
-rw-r--r--sys/compat/linux/linux_util.h92
9 files changed, 1202 insertions, 380 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 0918f221fd3fa..93932dfca75f4 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_file.c,v 1.4 1995/11/22 07:43:45 bde Exp $
+ * $Id: linux_file.c,v 1.5 1995/12/15 03:06:50 peter Exp $
*/
#include <sys/param.h>
@@ -41,16 +41,15 @@
#include <sys/malloc.h>
#include <sys/exec.h>
#include <sys/dirent.h>
+#include <sys/sysproto.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
#include <ufs/ufs/dir.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
-
-struct linux_creat_args {
- char *path;
- int mode;
-};
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
int
linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
@@ -60,6 +59,10 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
int flags;
int mode;
} */ bsd_open_args;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
#ifdef DEBUG
printf("Linux-emul(%d): creat(%s, %d)\n",
@@ -71,12 +74,6 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
return open(p, &bsd_open_args, retval);
}
-struct linux_open_args {
- char *path;
- int flags;
- int mode;
-};
-
int
linux_open(struct proc *p, struct linux_open_args *args, int *retval)
{
@@ -86,7 +83,15 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval)
int mode;
} */ bsd_open_args;
int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ if (args->flags & LINUX_O_CREAT)
+ CHECKALTCREAT(p, &sg, args->path);
+ else
+ CHECKALTEXIST(p, &sg, args->path);
+
#ifdef DEBUG
printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
p->p_pid, args->path, args->flags, args->mode);
@@ -128,6 +133,10 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval)
if (fp->f_type == DTYPE_VNODE)
(fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
}
+#ifdef DEBUG
+ printf("Linux-emul(%d): open returns error %d\n",
+ p->p_pid, error);
+#endif
return error;
}
@@ -179,12 +188,6 @@ bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
}
-struct linux_fcntl_args {
- int fd;
- int cmd;
- int arg;
-};
-
int
linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
{
@@ -195,8 +198,19 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
int arg;
} */ fcntl_args;
struct linux_flock linux_flock;
- struct flock *bsd_flock =
- (struct flock *)ua_alloc_init(sizeof(struct flock));
+ struct flock *bsd_flock;
+ struct filedesc *fdp;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr va;
+ long pgid;
+ struct pgrp *pgrp;
+ struct tty *tp, *(*d_tty) __P((dev_t));
+ caddr_t sg;
+
+ sg = stackgap_init();
+ bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
+ d_tty = NULL;
#ifdef DEBUG
printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
@@ -269,22 +283,51 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
return fcntl(p, &fcntl_args, retval);
case LINUX_F_SETOWN:
- fcntl_args.cmd = F_SETOWN;
- return fcntl(p, &fcntl_args, retval);
-
case LINUX_F_GETOWN:
- fcntl_args.cmd = F_GETOWN;
- return fcntl(p, &fcntl_args, retval);
+ /*
+ * We need to route around the normal fcntl() for these calls,
+ * since it uses TIOC{G,S}PGRP, which is too restrictive for
+ * Linux F_{G,S}ETOWN semantics. For sockets, this problem
+ * does not exist.
+ */
+ fdp = p->p_fd;
+ if ((u_int)args->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return EBADF;
+ if (fp->f_type == DTYPE_SOCKET) {
+ fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
+ return fcntl(p, &fcntl_args, retval);
+ }
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VCHR)
+ return EINVAL;
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ d_tty = cdevsw[major(va.va_rdev)]->d_devtotty;
+ if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
+ return EINVAL;
+ if (args->cmd == LINUX_F_GETOWN) {
+ retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
+ return 0;
+ }
+ if ((long)args->arg <= 0) {
+ pgid = -(long)args->arg;
+ } else {
+ struct proc *p1 = pfind((long)args->arg);
+ if (p1 == 0)
+ return (ESRCH);
+ pgid = (long)p1->p_pgrp->pg_id;
+ }
+ pgrp = pgfind(pgid);
+ if (pgrp == NULL || pgrp->pg_session != p->p_session)
+ return EPERM;
+ tp->t_pgrp = pgrp;
+ return 0;
}
return EINVAL;
}
-struct linux_lseek_args {
- int fdes;
- unsigned long off;
- int whence;
-};
-
int
linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
{
@@ -308,6 +351,34 @@ linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
return error;
}
+int
+linux_llseek(struct proc *p, struct linux_llseek_args *args, int *retval)
+{
+ struct lseek_args bsd_args;
+ int error;
+ off_t off;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
+ p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
+#endif
+ off = (args->olow) | (((off_t) args->ohigh) << 32);
+
+ bsd_args.fd = args->fd;
+ bsd_args.offset = off;
+ bsd_args.whence = args->whence;
+
+ if ((error = lseek(p, &bsd_args, retval)))
+ return error;
+
+ if ((error = copyout(retval, (caddr_t)args->res, sizeof (off_t))))
+ return error;
+
+ retval[0] = 0;
+ return 0;
+}
+
+
struct linux_dirent {
long dino;
linux_off_t doff;
@@ -318,15 +389,20 @@ struct linux_dirent {
#define LINUX_RECLEN(de,namlen) \
ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
-struct linux_readdir_args {
- int fd;
- struct linux_dirent *dent;
- unsigned int count;
-};
-
int
linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
{
+ struct linux_getdents_args lda;
+
+ lda.fd = args->fd;
+ lda.dent = args->dent;
+ lda.count = 1;
+ return linux_getdents(p, &lda, retval);
+}
+
+int
+linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
+{
register struct dirent *bdp;
struct vnode *vp;
caddr_t inp, buf; /* BSD-format */
@@ -342,12 +418,12 @@ linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
int buflen, error, eofflag, nbytes, justone, blockoff;
#ifdef DEBUG
- printf("Linux-emul(%d): readdir(%d, *, %d)\n",
+ printf("Linux-emul(%d): getdents(%d, *, %d)\n",
p->p_pid, args->fd, args->count);
#endif
if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
return (error);
-}
+ }
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
@@ -390,7 +466,7 @@ again:
(u_int **) NULL);
if (error) {
goto out;
-}
+ }
inp = buf;
inp += blockoff;
@@ -398,7 +474,7 @@ again:
resid = nbytes;
if ((len = buflen - auio.uio_resid - blockoff) == 0) {
goto eof;
- }
+ }
while (len > 0) {
bdp = (struct dirent *) inp;
@@ -426,7 +502,7 @@ again:
strcpy(linux_dirent.dname, bdp->d_name);
if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
goto out;
- }
+ }
inp += reclen;
off += reclen;
outp += linuxreclen;
@@ -450,3 +526,238 @@ out:
free(buf, M_TEMP);
return error;
}
+
+/*
+ * These exist mainly for hooks for doing /compat/linux translation.
+ */
+
+int
+linux_access(struct proc *p, struct linux_access_args *args, int *retval)
+{
+ struct access_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): access(%s, %d)\n",
+ p->p_pid, args->path, args->flags);
+#endif
+ bsd.path = args->path;
+ bsd.flags = args->flags;
+
+ return access(p, &bsd, retval);
+}
+
+int
+linux_unlink(struct proc *p, struct linux_unlink_args *args, int *retval)
+{
+ struct unlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): unlink(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return unlink(p, &bsd, retval);
+}
+
+int
+linux_chdir(struct proc *p, struct linux_chdir_args *args, int *retval)
+{
+ struct chdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return chdir(p, &bsd, retval);
+}
+
+int
+linux_chmod(struct proc *p, struct linux_chmod_args *args, int *retval)
+{
+ struct chmod_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chmod(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return chmod(p, &bsd, retval);
+}
+
+int
+linux_chown(struct proc *p, struct linux_chown_args *args, int *retval)
+{
+ struct chown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chown(%s, %d, %d)\n",
+ p->p_pid, args->path, args->uid, args->gid);
+#endif
+ bsd.path = args->path;
+ /* XXX size casts here */
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+
+ return chown(p, &bsd, retval);
+}
+
+int
+linux_mkdir(struct proc *p, struct linux_mkdir_args *args, int *retval)
+{
+ struct mkdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): mkdir(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return mkdir(p, &bsd, retval);
+}
+
+int
+linux_rmdir(struct proc *p, struct linux_rmdir_args *args, int *retval)
+{
+ struct rmdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rmdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return rmdir(p, &bsd, retval);
+}
+
+int
+linux_rename(struct proc *p, struct linux_rename_args *args, int *retval)
+{
+ struct rename_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->from);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rename(%s, %s)\n",
+ p->p_pid, args->from, args->to);
+#endif
+ bsd.from = args->from;
+ bsd.to = args->to;
+
+ return rename(p, &bsd, retval);
+}
+
+int
+linux_symlink(struct proc *p, struct linux_symlink_args *args, int *retval)
+{
+ struct symlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): symlink(%s, %s)\n",
+ p->p_pid, args->path, args->to);
+#endif
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return symlink(p, &bsd, retval);
+}
+
+int
+linux_execve(struct proc *p, struct linux_execve_args *args, int *retval)
+{
+ struct execve_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): execve(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.fname = args->path;
+ bsd.argv = args->argp;
+ bsd.envv = args->envp;
+
+ return execve(p, &bsd, retval);
+}
+
+int
+linux_readlink(struct proc *p, struct linux_readlink_args *args, int *retval)
+{
+ struct readlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->name);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n",
+ p->p_pid, args->name, args->buf, args->count);
+#endif
+ bsd.path = args->name;
+ bsd.buf = args->buf;
+ bsd.count = args->count;
+
+ return readlink(p, &bsd, retval);
+}
+
+int
+linux_truncate(struct proc *p, struct linux_truncate_args *args, int *retval)
+{
+ struct otruncate_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): truncate(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return otruncate(p, &bsd, retval);
+}
+
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 03bc0315e942f..968092862bd9a 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_ioctl.c,v 1.4 1995/12/29 22:12:12 sos Exp $
+ * $Id: linux_ioctl.c,v 1.5 1995/12/30 00:42:25 sos Exp $
*/
#include <sys/param.h>
@@ -38,12 +38,16 @@
#include <sys/filedesc.h>
#include <sys/tty.h>
#include <sys/termios.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/sockio.h>
#include <machine/console.h>
#include <machine/soundcard.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
+#include <i386/linux/linux_proto.h>
struct linux_termios {
unsigned long c_iflag;
@@ -351,13 +355,6 @@ linux_to_bsd_termios(struct linux_termios *linux_termios,
#endif
}
-
-struct linux_ioctl_args {
- int fd;
- int cmd;
- int arg;
-};
-
int
linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
{
@@ -456,6 +453,38 @@ linux_ioctl(struct proc *p, struct linux_ioctl_args *args, int *retval)
args->cmd = TIOCNOTTY;
return ioctl(p, (struct ioctl_args *)args, retval);
+ case LINUX_SIOCGIFCONF:
+ args->cmd = OSIOCGIFCONF;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCGIFFLAGS:
+ args->cmd = SIOCGIFFLAGS;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCGIFADDR:
+ args->cmd = OSIOCGIFADDR;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCGIFDSTADDR:
+ args->cmd = OSIOCGIFDSTADDR;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCGIFBRDADDR:
+ args->cmd = OSIOCGIFBRDADDR;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCGIFNETMASK:
+ args->cmd = OSIOCGIFNETMASK;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCADDMULTI:
+ args->cmd = SIOCADDMULTI;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
+ case LINUX_SIOCDELMULTI:
+ args->cmd = SIOCDELMULTI;
+ return ioctl(p, (struct ioctl_args *)args, retval);
+
case LINUX_TIOCSETD:
switch (args->arg) {
case LINUX_N_TTY:
diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c
index 2e5b924bc38cf..854766b99cc87 100644
--- a/sys/compat/linux/linux_ipc.c
+++ b/sys/compat/linux/linux_ipc.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_ipc.c,v 1.5 1996/01/05 19:52:49 wollman Exp $
+ * $Id: linux_ipc.c,v 1.6 1996/01/08 04:34:54 peter Exp $
*/
@@ -36,7 +36,20 @@
#include <sys/shm.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
+
+static int linux_semop __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_semget __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_semctl __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_msgsnd __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_msgrcv __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_msgop __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_msgctl __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_shmat __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_shmdt __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_shmget __P((struct proc *, struct linux_ipc_args *, int *));
+static int linux_shmctl __P((struct proc *, struct linux_ipc_args *, int *));
struct linux_ipc_perm {
linux_key_t key;
@@ -115,33 +128,25 @@ bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp)
lsp->private3 = bsp->shm_internal; /* this goes (yet) SOS */
}
-struct linux_ipc_args {
- int what;
- int arg1;
- int arg2;
- int arg3;
- caddr_t ptr;
-};
-
-int
+static int
linux_semop(struct proc *p, struct linux_ipc_args *args, int *retval)
{
return ENOSYS;
}
-int
+static int
linux_semget(struct proc *p, struct linux_ipc_args *args, int *retval)
{
return ENOSYS;
}
-int
+static int
linux_semctl(struct proc *p, struct linux_ipc_args *args, int *retval)
{
return ENOSYS;
}
-int
+static int
linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct msgsnd_args /* {
@@ -158,7 +163,7 @@ linux_msgsnd(struct proc *p, struct linux_ipc_args *args, int *retval)
return msgsnd(p, &bsd_args, retval);
}
-int
+static int
linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct msgrcv_args /* {
@@ -177,7 +182,7 @@ linux_msgrcv(struct proc *p, struct linux_ipc_args *args, int *retval)
return msgrcv(p, &bsd_args, retval);
}
-int
+static int
linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct msgget_args /* {
@@ -190,7 +195,7 @@ linux_msgget(struct proc *p, struct linux_ipc_args *args, int *retval)
return msgget(p, &bsd_args, retval);
}
-int
+static int
linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct msgctl_args /* {
@@ -205,7 +210,7 @@ linux_msgctl(struct proc *p, struct linux_ipc_args *args, int *retval)
return msgctl(p, &bsd_args, retval);
}
-int
+static int
linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct shmat_args /* {
@@ -226,7 +231,7 @@ linux_shmat(struct proc *p, struct linux_ipc_args *args, int *retval)
return 0;
}
-int
+static int
linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct shmdt_args /* {
@@ -237,7 +242,7 @@ linux_shmdt(struct proc *p, struct linux_ipc_args *args, int *retval)
return shmdt(p, &bsd_args, retval);
}
-int
+static int
linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct shmget_args /* {
@@ -252,7 +257,7 @@ linux_shmget(struct proc *p, struct linux_ipc_args *args, int *retval)
return shmget(p, &bsd_args, retval);
}
-int
+static int
linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
{
struct shmid_ds bsd_shmid;
@@ -263,12 +268,13 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
struct shmid_ds *buf;
} */ bsd_args;
int error;
+ caddr_t sg = stackgap_init();
switch (args->arg2) {
case LINUX_IPC_STAT:
bsd_args.shmid = args->arg1;
bsd_args.cmd = IPC_STAT;
- bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
if ((error = shmctl(p, &bsd_args, retval)))
return error;
if ((error = copyin((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
@@ -282,7 +288,7 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
sizeof(linux_shmid))))
return error;
linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
- bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
sizeof(struct shmid_ds))))
return error;
@@ -297,7 +303,7 @@ linux_shmctl(struct proc *p, struct linux_ipc_args *args, int *retval)
sizeof(linux_shmid))))
return error;
linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid);
- bsd_args.buf = (struct shmid_ds*)ua_alloc_init(sizeof(struct shmid_ds));
+ bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
if ((error = copyout((caddr_t)&bsd_shmid, (caddr_t)bsd_args.buf,
sizeof(struct shmid_ds))))
return error;
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index bc6e8d824b290..069ca28cf7390 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -6,7 +6,7 @@
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
+ * notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_misc.c,v 1.11 1996/01/19 22:59:24 dyson Exp $
+ * $Id: linux_misc.c,v 1.12 1996/02/16 18:40:50 peter Exp $
*/
#include <sys/param.h>
@@ -50,6 +50,7 @@
#include <sys/utsname.h>
#include <sys/vnode.h>
#include <sys/wait.h>
+#include <sys/time.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -64,11 +65,8 @@
#include <machine/psl.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
-
-struct linux_alarm_args {
- unsigned int secs;
-};
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
int
linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
@@ -110,10 +108,6 @@ linux_alarm(struct proc *p, struct linux_alarm_args *args, int *retval)
return 0;
}
-struct linux_brk_args {
- linux_caddr_t dsend;
-};
-
int
linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
{
@@ -136,7 +130,7 @@ linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
return ENOMEM;
error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE,
VM_PROT_ALL, VM_PROT_ALL, 0);
- if (error)
+ if (error)
return error;
vm->vm_dsize += btoc((new-old));
*retval = (int)(vm->vm_daddr + ctob(vm->vm_dsize));
@@ -164,10 +158,6 @@ linux_brk(struct proc *p, struct linux_brk_args *args, int *retval)
#endif
}
-struct linux_uselib_args {
- char *library;
-};
-
int
linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
{
@@ -178,12 +168,13 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
unsigned long vmaddr, file_offset;
unsigned long buffer, bss_size;
char *ptr;
- char path[MAXPATHLEN];
- const char *prefix = "/compat/linux";
- size_t sz, len;
int error;
+ caddr_t sg;
int locked;
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->library);
+
#ifdef DEBUG
printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library);
#endif
@@ -192,20 +183,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args, int *retval)
locked = 0;
vp = NULL;
- for (ptr = path; (*ptr = *prefix) != '\0'; ptr++, prefix++) ;
- sz = MAXPATHLEN - (ptr - path);
- if (error = copyinstr(args->library, ptr, sz, &len))
- goto cleanup;
- if (*ptr != '/') {
- error = EINVAL;
- goto cleanup;
- }
-
-#ifdef DEBUG
- printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, path);
-#endif
-
- NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p);
+ NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p);
if (error = namei(&ni))
goto cleanup;
@@ -361,7 +339,7 @@ printf("uselib: Non page aligned binary %d\n", file_offset);
goto cleanup;
/* copy from kernel VM space to user space */
- error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
+ error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr,
a_out->a_text + a_out->a_data);
/* release temporary kernel space */
@@ -404,7 +382,7 @@ printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]);
/*
* allocate some 'anon' space
*/
- error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
+ error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr,
bss_size, FALSE,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
@@ -427,49 +405,138 @@ cleanup:
return error;
}
-struct linux_select_args {
- void *ptr;
+/* XXX move */
+struct linux_select_argv {
+ int nfds;
+ fd_set *readfds;
+ fd_set *writefds;
+ fd_set *exceptfds;
+ struct timeval *timeout;
};
int
linux_select(struct proc *p, struct linux_select_args *args, int *retval)
{
- struct {
- int nfds;
- fd_set *readfds;
- fd_set *writefds;
- fd_set *exceptfds;
- struct timeval *timeout;
- } linux_args;
- struct select_args /* {
- unsigned int nd;
- fd_set *in;
- fd_set *ou;
- fd_set *ex;
- struct timeval *tv;
- } */ bsd_args;
+ struct linux_select_argv linux_args;
+ struct linux_newselect_args newsel;
int error;
+#ifdef SELECT_DEBUG
+ printf("Linux-emul(%d): select(%x)\n",
+ p->p_pid, args->ptr);
+#endif
if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
sizeof(linux_args))))
return error;
+
+ newsel.nfds = linux_args.nfds;
+ newsel.readfds = linux_args.readfds;
+ newsel.writefds = linux_args.writefds;
+ newsel.exceptfds = linux_args.exceptfds;
+ newsel.timeout = linux_args.timeout;
+
+ return linux_newselect(p, &newsel, retval);
+}
+
+int
+linux_newselect(struct proc *p, struct linux_newselect_args *args, int *retval)
+{
+ struct select_args bsa;
+ struct timeval tv0, tv1, utv, *tvp;
+ caddr_t sg;
+ int error;
+
#ifdef DEBUG
- printf("Linux-emul(%d): select(%d, %d, %d, %d, %d)\n",
- p->p_pid, linux_args.nfds, linux_args.readfds,
- linux_args.writefds, linux_args.exceptfds,
- linux_args.timeout);
+ printf("Linux-emul(%d): newselect(%d, %x, %x, %x, %x)\n",
+ p->p_pid, args->nfds, args->readfds, args->writefds,
+ args->exceptfds, args->timeout);
#endif
- bsd_args.nd = linux_args.nfds;
- bsd_args.in = linux_args.readfds;
- bsd_args.ou = linux_args.writefds;
- bsd_args.ex = linux_args.exceptfds;
- bsd_args.tv = linux_args.timeout;
- return select(p, &bsd_args, retval);
-}
+ error = 0;
+ bsa.nd = args->nfds;
+ bsa.in = args->readfds;
+ bsa.ou = args->writefds;
+ bsa.ex = args->exceptfds;
+ bsa.tv = args->timeout;
-struct linux_getpgid_args {
- int pid;
-};
+ /*
+ * Store current time for computation of the amount of
+ * time left.
+ */
+ if (args->timeout) {
+ if ((error = copyin(args->timeout, &utv, sizeof(utv))))
+ goto select_out;
+#ifdef DEBUG
+ printf("Linux-emul(%d): incoming timeout (%d/%d)\n",
+ p->p_pid, utv.tv_sec, utv.tv_usec);
+#endif
+ if (itimerfix(&utv)) {
+ /*
+ * The timeval was invalid. Convert it to something
+ * valid that will act as it does under Linux.
+ */
+ sg = stackgap_init();
+ tvp = stackgap_alloc(&sg, sizeof(utv));
+ utv.tv_sec += utv.tv_usec / 1000000;
+ utv.tv_usec %= 1000000;
+ if (utv.tv_usec < 0) {
+ utv.tv_sec -= 1;
+ utv.tv_usec += 1000000;
+ }
+ if (utv.tv_sec < 0)
+ timerclear(&utv);
+ if ((error = copyout(&utv, tvp, sizeof(utv))))
+ goto select_out;
+ bsa.tv = tvp;
+ }
+ microtime(&tv0);
+ }
+
+ error = select(p, &bsa, retval);
+#ifdef DEBUG
+ printf("Linux-emul(%d): real select returns %d\n",
+ p->p_pid, error);
+#endif
+
+ if (error) {
+ /*
+ * See fs/select.c in the Linux kernel. Without this,
+ * Maelstrom doesn't work.
+ */
+ if (error == ERESTART)
+ error = EINTR;
+ goto select_out;
+ }
+
+ if (args->timeout) {
+ if (*retval) {
+ /*
+ * Compute how much time was left of the timeout,
+ * by subtracting the current time and the time
+ * before we started the call, and subtracting
+ * that result from the user-supplied value.
+ */
+ microtime(&tv1);
+ timevalsub(&tv1, &tv0);
+ timevalsub(&utv, &tv1);
+ if (utv.tv_sec < 0)
+ timerclear(&utv);
+ } else
+ timerclear(&utv);
+#ifdef DEBUG
+ printf("Linux-emul(%d): outgoing timeout (%d/%d)\n",
+ p->p_pid, utv.tv_sec, utv.tv_usec);
+#endif
+ if ((error = copyout(&utv, args->timeout, sizeof(utv))))
+ goto select_out;
+ }
+
+select_out:
+#ifdef DEBUG
+ printf("Linux-emul(%d): newselect_out -> %d\n",
+ p->p_pid, error);
+#endif
+ return error;
+}
int
linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
@@ -490,35 +557,33 @@ linux_getpgid(struct proc *p, struct linux_getpgid_args *args, int *retval)
}
int
-linux_fork(struct proc *p, void *args, int *retval)
+linux_fork(struct proc *p, struct linux_fork_args *args, int *retval)
{
int error;
#ifdef DEBUG
printf("Linux-emul(%d): fork()\n", p->p_pid);
#endif
- if (error = fork(p, args, retval))
+ if (error = fork(p, (struct fork_args *)args, retval))
return error;
if (retval[1] == 1)
retval[0] = 0;
return 0;
}
-struct linux_mmap_args {
- void *ptr;
-};
-
-int
-linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
-{
- struct {
+/* XXX move */
+struct linux_mmap_argv {
linux_caddr_t addr;
int len;
int prot;
int flags;
int fd;
int pos;
- } linux_args;
+};
+
+int
+linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
+{
struct mmap_args /* {
caddr_t addr;
size_t len;
@@ -529,13 +594,14 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
off_t pos;
} */ bsd_args;
int error;
+ struct linux_mmap_argv linux_args;
if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args,
sizeof(linux_args))))
return error;
#ifdef DEBUG
printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n",
- p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
+ p->p_pid, linux_args.addr, linux_args.len, linux_args.prot,
linux_args.flags, linux_args.fd, linux_args.pos);
#endif
bsd_args.flags = 0;
@@ -556,9 +622,17 @@ linux_mmap(struct proc *p, struct linux_mmap_args *args, int *retval)
return mmap(p, &bsd_args, retval);
}
-struct linux_pipe_args {
- int *pipefds;
-};
+int
+linux_msync(struct proc *p, struct linux_msync_args *args, int *retval)
+{
+ struct msync_args bsd_args;
+
+ bsd_args.addr = args->addr;
+ bsd_args.len = args->len;
+ bsd_args.flags = 0; /* XXX ignore */
+
+ return msync(p, &bsd_args, retval);
+}
int
linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
@@ -576,10 +650,6 @@ linux_pipe(struct proc *p, struct linux_pipe_args *args, int *retval)
return 0;
}
-struct linux_time_args {
- linux_time_t *tm;
-};
-
int
linux_time(struct proc *p, struct linux_time_args *args, int *retval)
{
@@ -592,28 +662,24 @@ linux_time(struct proc *p, struct linux_time_args *args, int *retval)
#endif
microtime(&tv);
tm = tv.tv_sec;
- if (error = copyout(&tm, args->tm, sizeof(linux_time_t)))
+ if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t))))
return error;
- *retval = tv.tv_sec;
+ *retval = tm;
return 0;
}
-struct linux_tms {
+struct linux_times_argv {
long tms_utime;
long tms_stime;
long tms_cutime;
long tms_cstime;
};
-struct linux_tms_args {
- char *buf;
-};
-
int
-linux_times(struct proc *p, struct linux_tms_args *args, int *retval)
+linux_times(struct proc *p, struct linux_times_args *args, int *retval)
{
struct timeval tv;
- struct linux_tms tms;
+ struct linux_times_argv tms;
#ifdef DEBUG
printf("Linux-emul(%d): times(*)\n", p->p_pid);
@@ -627,9 +693,10 @@ linux_times(struct proc *p, struct linux_tms_args *args, int *retval)
microtime(&tv);
*retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
return (copyout((caddr_t)&tms, (caddr_t)args->buf,
- sizeof(struct linux_tms)));
+ sizeof(struct linux_times_argv)));
}
+/* XXX move */
struct linux_newuname_t {
char sysname[65];
char nodename[65];
@@ -639,10 +706,6 @@ struct linux_newuname_t {
char domainname[65];
};
-struct linux_newuname_args {
- char *buf;
-};
-
int
linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
{
@@ -662,10 +725,6 @@ linux_newuname(struct proc *p, struct linux_newuname_args *args, int *retval)
sizeof(struct linux_newuname_t)));
}
-struct linux_utime_args {
- char *fname;
- linux_time_t *timeptr;
-};
int
linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
@@ -675,23 +734,21 @@ linux_utime(struct proc *p, struct linux_utime_args *args, int *retval)
struct timeval *tptr;
} */ bsdutimes;
struct timeval tv;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->fname);
#ifdef DEBUG
printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname);
#endif
- tv.tv_sec = (long)args->timeptr;
+ tv.tv_sec = (long)args->timeptr; /* XXX: wrong?? */
tv.tv_usec = 0;
bsdutimes.tptr = &tv;
bsdutimes.path = args->fname;
return utimes(p, &bsdutimes, retval);
}
-struct linux_waitpid_args {
- int pid;
- int *status;
- int options;
-};
-
int
linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
{
@@ -704,8 +761,8 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
int error, tmpstat;
#ifdef DEBUG
- printf("Linux-emul(%d): waitpid(%d, *, %d)\n",
- p->p_pid, args->pid, args->options);
+ printf("Linux-emul(%d): waitpid(%d, 0x%x, %d)\n",
+ p->p_pid, args->pid, args->status, args->options);
#endif
tmp.pid = args->pid;
tmp.status = args->status;
@@ -714,25 +771,21 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args, int *retval)
if (error = wait4(p, &tmp, retval))
return error;
- if (error = copyin(args->status, &tmpstat, sizeof(int)))
- return error;
- if (WIFSIGNALED(tmpstat))
- tmpstat = (tmpstat & 0xffffff80) |
- bsd_to_linux_signal[WTERMSIG(tmpstat)];
- else if (WIFSTOPPED(tmpstat))
- tmpstat = (tmpstat & 0xffff00ff) |
- (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
- return copyout(&tmpstat, args->status, sizeof(int));
+ if (args->status) {
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+ } else
+ return 0;
}
-struct linux_wait4_args {
- int pid;
- int *status;
- int options;
- struct rusage *rusage;
-};
-
-int
+int
linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
{
struct wait_args /* {
@@ -744,8 +797,8 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
int error, tmpstat;
#ifdef DEBUG
- printf("Linux-emul(%d): wait4(%d, *, %d, *)\n",
- p->p_pid, args->pid, args->options);
+ printf("Linux-emul(%d): wait4(%d, 0x%x, %d, 0x%x)\n",
+ p->p_pid, args->pid, args->status, args->options, args->rusage);
#endif
tmp.pid = args->pid;
tmp.status = args->status;
@@ -754,28 +807,108 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args, int *retval)
if (error = wait4(p, &tmp, retval))
return error;
- if (error = copyin(args->status, &tmpstat, sizeof(int)))
- return error;
- if (WIFSIGNALED(tmpstat))
- tmpstat = (tmpstat & 0xffffff80) |
- bsd_to_linux_signal[WTERMSIG(tmpstat)];
- else if (WIFSTOPPED(tmpstat))
- tmpstat = (tmpstat & 0xffff00ff) |
- (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
- return copyout(&tmpstat, args->status, sizeof(int));
-}
-struct linux_mknod_args {
- char *path;
- int mode;
- int dev;
-};
+ p->p_siglist &= ~sigmask(SIGCHLD);
+
+ if (args->status) {
+ if (error = copyin(args->status, &tmpstat, sizeof(int)))
+ return error;
+ if (WIFSIGNALED(tmpstat))
+ tmpstat = (tmpstat & 0xffffff80) |
+ bsd_to_linux_signal[WTERMSIG(tmpstat)];
+ else if (WIFSTOPPED(tmpstat))
+ tmpstat = (tmpstat & 0xffff00ff) |
+ (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8);
+ return copyout(&tmpstat, args->status, sizeof(int));
+ } else
+ return 0;
+}
-int
+int
linux_mknod(struct proc *p, struct linux_mknod_args *args, int *retval)
{
- if (args->mode & S_IFIFO)
- return mkfifo(p, (struct mkfifo_args *)args, retval);
- else
- return mknod(p, (struct mknod_args *)args, retval);
+ caddr_t sg;
+ struct mknod_args bsd_mknod;
+ struct mkfifo_args bsd_mkfifo;
+
+ sg = stackgap_init();
+
+ CHECKALTCREAT(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): mknod(%s, %d, %d)\n",
+ p->p_pid, args->path, args->mode, args->dev);
+#endif
+
+ if (args->mode & S_IFIFO) {
+ bsd_mkfifo.path = args->path;
+ bsd_mkfifo.mode = args->mode;
+ return mkfifo(p, &bsd_mkfifo, retval);
+ } else {
+ bsd_mknod.path = args->path;
+ bsd_mknod.mode = args->mode;
+ bsd_mknod.dev = args->dev;
+ return mknod(p, &bsd_mknod, retval);
+ }
+}
+
+/*
+ * UGH! This is just about the dumbest idea I've ever heard!!
+ */
+int
+linux_personality(struct proc *p, struct linux_personality_args *args,
+ int *retval)
+{
+#ifdef DEBUG
+ printf("Linux-emul(%d): personality(%d)\n",
+ p->p_pid, args->per);
+#endif
+ if (args->per != 0)
+ return EINVAL;
+
+ /* Yes Jim, it's still a Linux... */
+ retval[0] = 0;
+ return 0;
+}
+
+/*
+ * Wrappers for get/setitimer for debugging..
+ */
+int
+linux_setitimer(struct proc *p, struct linux_setitimer_args *args, int *retval)
+{
+ struct setitimer_args bsa;
+ struct itimerval foo;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): setitimer(%08x, %08x)\n",
+ p->p_pid, args->itv, args->oitv);
+#endif
+ bsa.which = args->which;
+ bsa.itv = args->itv;
+ bsa.oitv = args->oitv;
+ if (args->itv) {
+ if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo,
+ sizeof(foo))))
+ return error;
+#ifdef DEBUG
+ printf("setitimer: value: sec: %d, usec: %d\n", foo.it_value.tv_sec, foo.it_value.tv_usec);
+ printf("setitimer: interval: sec: %d, usec: %d\n", foo.it_interval.tv_sec, foo.it_interval.tv_usec);
+#endif
+ }
+ return setitimer(p, &bsa, retval);
+}
+
+int
+linux_getitimer(struct proc *p, struct linux_getitimer_args *args, int *retval)
+{
+ struct getitimer_args bsa;
+#ifdef DEBUG
+ printf("Linux-emul(%d): getitimer(%08x)\n",
+ p->p_pid, args->itv);
+#endif
+ bsa.which = args->which;
+ bsa.itv = args->itv;
+ return getitimer(p, &bsa, retval);
}
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index fc5c2cd7c2747..32648cb217a9e 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_signal.c,v 1.2 1995/11/22 07:43:50 bde Exp $
+ * $Id: linux_signal.c,v 1.3 1995/12/15 03:06:56 peter Exp $
*/
#include <sys/param.h>
@@ -37,69 +37,96 @@
#include <sys/signalvar.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
-
-#define DONTMASK (sigmask(SIGKILL)|sigmask(SIGSTOP)|sigmask(SIGCHLD))
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
static sigset_t
-linux_to_bsd_sigmask(linux_sigset_t mask) {
- int i;
+linux_to_bsd_sigset(linux_sigset_t mask) {
+ int b, l;
sigset_t new = 0;
- for (i = 1; i <= LINUX_NSIG; i++)
- if (mask & (1 << i-1))
- new |= (1 << (linux_to_bsd_signal[i]-1));
+ for (l = 1; l <= LINUX_NSIG; l++) {
+ if (mask & (1 << (l - 1))) {
+ if ((b = linux_to_bsd_signal[l]))
+ new |= (1 << (b - 1));
+ }
+ }
return new;
}
static linux_sigset_t
-bsd_to_linux_sigmask(sigset_t mask) {
- int i;
+bsd_to_linux_sigset(sigset_t mask) {
+ int b, l;
sigset_t new = 0;
- for (i = 1; i <= NSIG; i++)
- if (mask & (1 << i-1))
- new |= (1 << (bsd_to_linux_signal[i]-1));
+ for (b = 1; b <= NSIG; b++) {
+ if (mask & (1 << (b - 1))) {
+ if ((l = bsd_to_linux_signal[b]))
+ new |= (1 << (l - 1));
+ }
+ }
return new;
}
-struct linux_sigaction_args {
- int sig;
- linux_sigaction_t *nsa;
- linux_sigaction_t *osa;
-};
+void
+linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa)
+{
+ bsa->sa_mask = linux_to_bsd_sigset(lsa->sa_mask);
+ bsa->sa_handler = lsa->sa_handler;
+ bsa->sa_flags = 0;
+ if (lsa->sa_flags & LINUX_SA_NOCLDSTOP)
+ bsa->sa_flags |= SA_NOCLDSTOP;
+ if (lsa->sa_flags & LINUX_SA_ONSTACK)
+ bsa->sa_flags |= SA_ONSTACK;
+ if (lsa->sa_flags & LINUX_SA_RESTART)
+ bsa->sa_flags |= SA_RESTART;
+ if (lsa->sa_flags & LINUX_SA_ONESHOT)
+ bsa->sa_flags |= SA_RESETHAND;
+ if (lsa->sa_flags & LINUX_SA_NOMASK)
+ bsa->sa_flags |= SA_NODEFER;
+}
+
+void
+bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa)
+{
+ lsa->sa_handler = bsa->sa_handler;
+ lsa->sa_restorer = NULL; /* unsupported */
+ lsa->sa_mask = bsd_to_linux_sigset(bsa->sa_mask);
+ lsa->sa_flags = 0;
+ if (bsa->sa_flags & SA_NOCLDSTOP)
+ lsa->sa_flags |= LINUX_SA_NOCLDSTOP;
+ if (bsa->sa_flags & SA_ONSTACK)
+ lsa->sa_flags |= LINUX_SA_ONSTACK;
+ if (bsa->sa_flags & SA_RESTART)
+ lsa->sa_flags |= LINUX_SA_RESTART;
+ if (bsa->sa_flags & SA_RESETHAND)
+ lsa->sa_flags |= LINUX_SA_ONESHOT;
+ if (bsa->sa_flags & SA_NODEFER)
+ lsa->sa_flags |= LINUX_SA_NOMASK;
+}
int
linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
{
linux_sigaction_t linux_sa;
struct sigaction *nsa = NULL, *osa = NULL, bsd_sa;
- struct sigaction_args /* {
- int signum;
- struct sigaction *nsa;
- struct sigaction *osa;
- } */ sa;
+ struct sigaction_args sa;
int error;
+ caddr_t sg = stackgap_init();
#ifdef DEBUG
- printf("Linux-emul(%d): sigaction(%d, *, *)\n", p->p_pid, args->sig);
+ printf("Linux-emul(%d): sigaction(%d, %08x, %08x)\n", p->p_pid, args->sig,
+ args->nsa, args->osa);
#endif
+
if (args->osa)
- osa = (struct sigaction *)ua_alloc_init(sizeof(struct sigaction));
+ osa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction));
if (args->nsa) {
- nsa = (struct sigaction *)ua_alloc(sizeof(struct sigaction));
+ nsa = (struct sigaction *)stackgap_alloc(&sg, sizeof(struct sigaction));
if (error = copyin(args->nsa, &linux_sa, sizeof(linux_sigaction_t)))
return error;
- bsd_sa.sa_mask = linux_to_bsd_sigmask(linux_sa.sa_mask);
- bsd_sa.sa_handler = linux_sa.sa_handler;
- bsd_sa.sa_flags = 0;
- if (linux_sa.sa_flags & LINUX_SA_NOCLDSTOP)
- bsd_sa.sa_flags |= SA_NOCLDSTOP;
- if (linux_sa.sa_flags & LINUX_SA_ONSTACK)
- bsd_sa.sa_flags |= SA_ONSTACK;
- if (linux_sa.sa_flags & LINUX_SA_RESTART)
- bsd_sa.sa_flags |= SA_RESTART;
+ linux_to_bsd_sigaction(&linux_sa, &bsd_sa);
if (error = copyout(&bsd_sa, nsa, sizeof(struct sigaction)))
return error;
}
@@ -112,27 +139,49 @@ linux_sigaction(struct proc *p, struct linux_sigaction_args *args, int *retval)
if (args->osa) {
if (error = copyin(osa, &bsd_sa, sizeof(struct sigaction)))
return error;
- linux_sa.sa_handler = bsd_sa.sa_handler;
- linux_sa.sa_restorer = NULL;
- linux_sa.sa_mask = bsd_to_linux_sigmask(bsd_sa.sa_mask);
- linux_sa.sa_flags = 0;
- if (bsd_sa.sa_flags & SA_NOCLDSTOP)
- linux_sa.sa_flags |= LINUX_SA_NOCLDSTOP;
- if (bsd_sa.sa_flags & SA_ONSTACK)
- linux_sa.sa_flags |= LINUX_SA_ONSTACK;
- if (bsd_sa.sa_flags & SA_RESTART)
- linux_sa.sa_flags |= LINUX_SA_RESTART;
+ bsd_to_linux_sigaction(&bsd_sa, &linux_sa);
if (error = copyout(&linux_sa, args->osa, sizeof(linux_sigaction_t)))
return error;
}
return 0;
}
-struct linux_sigprocmask_args {
- int how;
- linux_sigset_t *mask;
- linux_sigset_t *omask;
-};
+int
+linux_signal(struct proc *p, struct linux_signal_args *args, int *retval)
+{
+ caddr_t sg;
+ struct sigaction_args sa_args;
+ struct sigaction *osa, *nsa, tmpsa;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): signal(%d, %08x)\n", p->p_pid,
+ args->sig, args->handler);
+#endif
+ sg = stackgap_init();
+ nsa = stackgap_alloc(&sg, sizeof *nsa);
+ osa = stackgap_alloc(&sg, sizeof *osa);
+
+ tmpsa.sa_handler = args->handler;
+ tmpsa.sa_mask = (sigset_t) 0;
+ tmpsa.sa_flags = SA_RESETHAND | SA_NODEFER;
+ if ((error = copyout(&tmpsa, nsa, sizeof tmpsa)))
+ return error;
+
+ sa_args.signum = linux_to_bsd_signal[args->sig];
+ sa_args.osa = osa;
+ sa_args.nsa = nsa;
+ if ((error = sigaction(p, &sa_args, retval)))
+ return error;
+
+ if ((error = copyin(osa, &tmpsa, sizeof *osa)))
+ return error;
+
+ *retval = (int)tmpsa.sa_handler;
+
+ return 0;
+}
+
int
linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
@@ -145,8 +194,11 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
#ifdef DEBUG
printf("Linux-emul(%d): sigprocmask(%d, *, *)\n", p->p_pid, args->how);
#endif
+
+ *retval = 0;
+
if (args->omask != NULL) {
- omask = bsd_to_linux_sigmask(p->p_sigmask);
+ omask = bsd_to_linux_sigset(p->p_sigmask);
if (error = copyout(&omask, args->omask, sizeof(sigset_t)))
return error;
}
@@ -155,17 +207,17 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
if (error = copyin(args->mask, &mask, sizeof(linux_sigset_t)))
return error;
- mask = linux_to_bsd_sigmask(mask);
+ mask = linux_to_bsd_sigset(mask);
s = splhigh();
switch (args->how) {
case LINUX_SIG_BLOCK:
- p->p_sigmask |= (mask & ~DONTMASK);
+ p->p_sigmask |= (mask & ~sigcantmask);
break;
case LINUX_SIG_UNBLOCK:
p->p_sigmask &= ~mask;
break;
case LINUX_SIG_SETMASK:
- p->p_sigmask = (mask & ~DONTMASK);
+ p->p_sigmask = (mask & ~sigcantmask);
break;
default:
error = EINVAL;
@@ -176,38 +228,33 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args,
}
int
-linux_siggetmask(struct proc *p, void *args, int *retval)
+linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args, int *retval)
{
#ifdef DEBUG
printf("Linux-emul(%d): siggetmask()\n", p->p_pid);
#endif
- *retval = bsd_to_linux_sigmask(p->p_sigmask);
+ *retval = bsd_to_linux_sigset(p->p_sigmask);
return 0;
}
-struct linux_sigsetmask_args {
- linux_sigset_t mask;
-};
-
int
linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args,int *retval)
{
int s;
+ sigset_t mask;
#ifdef DEBUG
printf("Linux-emul(%d): sigsetmask(%08x)\n", p->p_pid, args->mask);
#endif
+ *retval = bsd_to_linux_sigset(p->p_sigmask);
+
+ mask = linux_to_bsd_sigset(args->mask);
s = splhigh();
- p->p_sigmask = (linux_to_bsd_sigmask(args->mask) & ~DONTMASK);
+ p->p_sigmask = mask & ~sigcantmask;
splx(s);
- *retval = bsd_to_linux_sigmask(p->p_sigmask);
return 0;
}
-struct linux_sigpending_args {
- linux_sigset_t *mask;
-};
-
int
linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
{
@@ -216,32 +263,35 @@ linux_sigpending(struct proc *p, struct linux_sigpending_args *args,int *retval)
#ifdef DEBUG
printf("Linux-emul(%d): sigpending(*)\n", p->p_pid);
#endif
- linux_sig = bsd_to_linux_sigmask(p->p_siglist & p->p_sigmask);
+ linux_sig = bsd_to_linux_sigset(p->p_siglist & p->p_sigmask);
return copyout(&linux_sig, args->mask, sizeof(linux_sig));
}
-struct linux_sigsuspend_args {
- linux_sigset_t mask;
-};
-
int
linux_sigsuspend(struct proc *p, struct linux_sigsuspend_args *args,int *retval)
{
- struct sigsuspend_args /* {
- int mask;
- } */ tmp;
+ struct sigsuspend_args tmp;
+ int error;
#ifdef DEBUG
printf("Linux-emul(%d): sigsuspend(%08x)\n", p->p_pid, args->mask);
#endif
- tmp.mask = linux_to_bsd_sigmask(args->mask);
+ tmp.mask = linux_to_bsd_sigset(args->mask);
return sigsuspend(p, &tmp , retval);
}
-struct linux_kill_args {
- int pid;
- int signum;
-};
+int
+linux_pause(struct proc *p, struct linux_pause_args *args,int *retval)
+{
+ struct sigsuspend_args tmp;
+ int error;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): pause()\n", p->p_pid);
+#endif
+ tmp.mask = p->p_sigmask;
+ return sigsuspend(p, &tmp , retval);
+}
int
linux_kill(struct proc *p, struct linux_kill_args *args, int *retval)
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index da4668c674e10..63b33d50c9be2 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_socket.c,v 1.2 1995/11/22 07:43:50 bde Exp $
+ * $Id: linux_socket.c,v 1.3 1995/12/15 03:06:57 peter Exp $
*/
/* XXX we use functions that might not exist. */
@@ -41,7 +41,7 @@
#include <netinet/in.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
+#include <i386/linux/linux_proto.h>
static int
linux_to_bsd_domain(int domain)
@@ -555,11 +555,6 @@ linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args, int *retval
return getsockopt(p, &bsd_args, retval);
}
-struct linux_socketcall_args {
- int what;
- void *args;
-};
-
int
linux_socketcall(struct proc *p, struct linux_socketcall_args *args,int *retval)
{
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 327343bd544f0..8d562e0eff72e 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_stats.c,v 1.3 1995/11/22 07:43:51 bde Exp $
+ * $Id: linux_stats.c,v 1.4 1996/01/30 12:23:17 peter Exp $
*/
#include <sys/param.h>
@@ -42,7 +42,8 @@
#include <sys/pipe.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
struct linux_newstat {
unsigned short stat_dev;
@@ -67,10 +68,6 @@ struct linux_newstat {
unsigned long __unused5;
};
-struct linux_newstat_args {
- char *path;
- struct linux_newstat *buf;
-};
static int
newstat_copyout(struct stat *buf, void *ubuf)
@@ -97,9 +94,12 @@ int
linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
{
struct stat buf;
- struct linux_newstat tbuf;
struct nameidata nd;
int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
#ifdef DEBUG
printf("Linux-emul(%d): newstat(%s, *)\n", p->p_pid, args->path);
@@ -115,44 +115,78 @@ linux_newstat(struct proc *p, struct linux_newstat_args *args, int *retval)
return error;
}
+/*
+ * Get file status; this version does not follow links.
+ */
int
-linux_newlstat(struct proc *p, struct linux_newstat_args *args, int *retval)
+linux_newlstat(p, uap, retval)
+ struct proc *p;
+ struct linux_newlstat_args *uap;
+ int *retval;
{
- struct stat buf;
- struct linux_newstat tbuf;
- struct nameidata nd;
- int error;
+ int error;
+ struct vnode *vp, *dvp;
+ struct stat sb, sb1;
+ struct nameidata nd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, uap->path);
#ifdef DEBUG
- printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, args->path);
+ printf("Linux-emul(%d): newlstat(%s, *)\n", p->p_pid, uap->path);
#endif
- NDINIT(&nd, LOOKUP, LOCKLEAF|FOLLOW, UIO_USERSPACE, args->path, p);
- error = namei(&nd);
- if (!error) {
- error = vn_stat(nd.ni_vp, &buf, p);
- vput(nd.ni_vp);
- }
- if (!error)
- error = newstat_copyout(&buf, args->buf);
- return error;
+ NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
+ uap->path, p);
+ error = namei(&nd);
+ if (error)
+ return (error);
+ /*
+ * For symbolic links, always return the attributes of its
+ * containing directory, except for mode, size, and links.
+ */
+ vp = nd.ni_vp;
+ dvp = nd.ni_dvp;
+ if (vp->v_type != VLNK) {
+ if (dvp == vp)
+ vrele(dvp);
+ else
+ vput(dvp);
+ error = vn_stat(vp, &sb, p);
+ vput(vp);
+ if (error)
+ return (error);
+ } else {
+ error = vn_stat(dvp, &sb, p);
+ vput(dvp);
+ if (error) {
+ vput(vp);
+ return (error);
+ }
+ error = vn_stat(vp, &sb1, p);
+ vput(vp);
+ if (error)
+ return (error);
+ sb.st_mode &= ~S_IFDIR;
+ sb.st_mode |= S_IFLNK;
+ sb.st_nlink = sb1.st_nlink;
+ sb.st_size = sb1.st_size;
+ sb.st_blocks = sb1.st_blocks;
+ }
+ error = newstat_copyout(&sb, uap->buf);
+ return (error);
}
-struct linux_newfstat_args {
- int fd;
- struct linux_newstat *buf;
-};
-
int
linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
{
- struct linux_newstat tbuf;
struct filedesc *fdp = p->p_fd;
struct file *fp;
struct stat buf;
int error;
#ifdef DEBUG
- printf("Linux-emul(%d): newlstat(%d, *)\n", p->p_pid, args->fd);
+ printf("Linux-emul(%d): newfstat(%d, *)\n", p->p_pid, args->fd);
#endif
if ((unsigned)args->fd >= fdp->fd_nfiles
|| (fp = fdp->fd_ofiles[args->fd]) == NULL)
@@ -175,7 +209,7 @@ linux_newfstat(struct proc *p, struct linux_newfstat_args *args, int *retval)
return error;
}
-struct linux_statfs {
+struct linux_statfs_buf {
long ftype;
long fbsize;
long fblocks;
@@ -188,12 +222,6 @@ struct linux_statfs {
long fspare[6];
};
-
-struct linux_statfs_args {
- char *path;
- struct statfs *buf;
-};
-
int
linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
{
@@ -201,8 +229,12 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
struct nameidata *ndp;
struct statfs *bsd_statfs;
struct nameidata nd;
- struct linux_statfs linux_statfs;
+ struct linux_statfs_buf linux_statfs_buf;
int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
#ifdef DEBUG
printf("Linux-emul(%d): statfs(%s, *)\n", p->p_pid, args->path);
@@ -217,32 +249,27 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args, int *retval)
if (error = VFS_STATFS(mp, bsd_statfs, p))
return error;
bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- linux_statfs.ftype = bsd_statfs->f_type;
- linux_statfs.fbsize = bsd_statfs->f_bsize;
- linux_statfs.fblocks = bsd_statfs->f_blocks;
- linux_statfs.fbfree = bsd_statfs->f_bfree;
- linux_statfs.fbavail = bsd_statfs->f_bavail;
- linux_statfs.fffree = bsd_statfs->f_ffree;
- linux_statfs.ffiles = bsd_statfs->f_files;
- linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
- linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
- linux_statfs.fnamelen = MAXNAMLEN;
- return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
- sizeof(struct linux_statfs));
+ linux_statfs_buf.ftype = bsd_statfs->f_type;
+ linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
+ linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
+ linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
+ linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
+ linux_statfs_buf.fffree = bsd_statfs->f_ffree;
+ linux_statfs_buf.ffiles = bsd_statfs->f_files;
+ linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs_buf.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
+ sizeof(struct linux_statfs_buf));
}
-struct linux_fstatfs_args {
- int fd;
- struct statfs *buf;
-};
-
int
linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
{
struct file *fp;
struct mount *mp;
struct statfs *bsd_statfs;
- struct linux_statfs linux_statfs;
+ struct linux_statfs_buf linux_statfs_buf;
int error;
#ifdef DEBUG
@@ -255,16 +282,16 @@ linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args, int *retval)
if (error = VFS_STATFS(mp, bsd_statfs, p))
return error;
bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
- linux_statfs.ftype = bsd_statfs->f_type;
- linux_statfs.fbsize = bsd_statfs->f_bsize;
- linux_statfs.fblocks = bsd_statfs->f_blocks;
- linux_statfs.fbfree = bsd_statfs->f_bfree;
- linux_statfs.fbavail = bsd_statfs->f_bavail;
- linux_statfs.fffree = bsd_statfs->f_ffree;
- linux_statfs.ffiles = bsd_statfs->f_files;
- linux_statfs.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
- linux_statfs.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
- linux_statfs.fnamelen = MAXNAMLEN;
- return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf,
- sizeof(struct linux_statfs));
+ linux_statfs_buf.ftype = bsd_statfs->f_type;
+ linux_statfs_buf.fbsize = bsd_statfs->f_bsize;
+ linux_statfs_buf.fblocks = bsd_statfs->f_blocks;
+ linux_statfs_buf.fbfree = bsd_statfs->f_bfree;
+ linux_statfs_buf.fbavail = bsd_statfs->f_bavail;
+ linux_statfs_buf.fffree = bsd_statfs->f_ffree;
+ linux_statfs_buf.ffiles = bsd_statfs->f_files;
+ linux_statfs_buf.ffsid.val[0] = bsd_statfs->f_fsid.val[0];
+ linux_statfs_buf.ffsid.val[1] = bsd_statfs->f_fsid.val[1];
+ linux_statfs_buf.fnamelen = MAXNAMLEN;
+ return copyout((caddr_t)&linux_statfs_buf, (caddr_t)args->buf,
+ sizeof(struct linux_statfs_buf));
}
diff --git a/sys/compat/linux/linux_util.c b/sys/compat/linux/linux_util.c
new file mode 100644
index 0000000000000..1785fd315a109
--- /dev/null
+++ b/sys/compat/linux/linux_util.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
+ * $Id$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/vnode.h>
+
+#include <i386/linux/linux_util.h>
+
+const char linux_emul_path[] = "/compat/linux";
+
+/*
+ * Search an alternate path before passing pathname arguments on
+ * to system calls. Useful for keeping a seperate 'emulation tree'.
+ *
+ * If cflag is set, we check if an attempt can be made to create
+ * the named file, i.e. we check if the directory it should
+ * be in exists.
+ */
+int
+linux_emul_find(p, sgp, prefix, path, pbuf, cflag)
+ struct proc *p;
+ caddr_t *sgp; /* Pointer to stackgap memory */
+ const char *prefix;
+ char *path;
+ char **pbuf;
+ int cflag;
+{
+ struct nameidata nd;
+ struct nameidata ndroot;
+ struct vattr vat;
+ struct vattr vatroot;
+ int error;
+ char *ptr, *buf, *cp;
+ size_t sz, len;
+
+ buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ *pbuf = path;
+
+ for (ptr = buf; (*ptr = *prefix) != '\0'; ptr++, prefix++)
+ continue;
+
+ sz = MAXPATHLEN - (ptr - buf);
+
+ /*
+ * If sgp is not given then the path is already in kernel space
+ */
+ if (sgp == NULL)
+ error = copystr(path, ptr, sz, &len);
+ else
+ error = copyinstr(path, ptr, sz, &len);
+
+ if (error) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ if (*ptr != '/') {
+ free(buf, M_TEMP);
+ return EINVAL;
+ }
+
+ /*
+ * We know that there is a / somewhere in this pathname.
+ * Search backwards for it, to find the file's parent dir
+ * to see if it exists in the alternate tree. If it does,
+ * and we want to create a file (cflag is set). We don't
+ * need to worry about the root comparison in this case.
+ */
+
+ if (cflag) {
+ for (cp = &ptr[len] - 1; *cp != '/'; cp--);
+ *cp = '\0';
+
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ *cp = '/';
+ }
+ else {
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p);
+
+ if ((error = namei(&nd)) != 0) {
+ free(buf, M_TEMP);
+ return error;
+ }
+
+ /*
+ * We now compare the vnode of the linux_root to the one
+ * vnode asked. If they resolve to be the same, then we
+ * ignore the match so that the real root gets used.
+ * This avoids the problem of traversing "../.." to find the
+ * root directory and never finding it, because "/" resolves
+ * to the emulation root directory. This is expensive :-(
+ */
+ /* XXX: prototype should have const here for NDINIT */
+ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE,
+ (char *) linux_emul_path, p);
+
+ if ((error = namei(&ndroot)) != 0) {
+ /* Cannot happen! */
+ free(buf, M_TEMP);
+ vrele(nd.ni_vp);
+ return error;
+ }
+
+ if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) {
+ goto done;
+ }
+
+ if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p))
+ != 0) {
+ goto done;
+ }
+
+ if (vat.va_fsid == vatroot.va_fsid &&
+ vat.va_fileid == vatroot.va_fileid) {
+ error = ENOENT;
+ goto done;
+ }
+
+ }
+ if (sgp == NULL)
+ *pbuf = buf;
+ else {
+ sz = &ptr[len] - buf;
+ *pbuf = stackgap_alloc(sgp, sz + 1);
+ error = copyout(buf, *pbuf, sz);
+ free(buf, M_TEMP);
+ }
+
+
+done:
+ vrele(nd.ni_vp);
+ if (!cflag)
+ vrele(ndroot.ni_vp);
+ return error;
+}
diff --git a/sys/compat/linux/linux_util.h b/sys/compat/linux/linux_util.h
new file mode 100644
index 0000000000000..46edfc52aae98
--- /dev/null
+++ b/sys/compat/linux/linux_util.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * Copyright (c) 1995 Frank van der Linden
+ * Copyright (c) 1995 Scott Bartram
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from: svr4_util.h,v 1.5 1994/11/18 02:54:31 christos Exp
+ * from: linux_util.h,v 1.2 1995/03/05 23:23:50 fvdl Exp
+ * $Id$
+ */
+
+/*
+ * This file is pretty much the same as Christos' svr4_util.h
+ * (for now).
+ */
+
+#ifndef _LINUX_UTIL_H_
+#define _LINUX_UTIL_H_
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#include <sys/exec.h>
+#include <sys/sysent.h>
+#include <sys/cdefs.h>
+
+#ifndef SCARG
+#define SCARG(p, x) (p)->x
+#endif
+
+static __inline caddr_t stackgap_init(void);
+static __inline void *stackgap_alloc(caddr_t *, size_t);
+
+static __inline caddr_t
+stackgap_init()
+{
+#define szsigcode (*(curproc->p_sysent->sv_szsigcode), sizeof(char *))
+ return (caddr_t)(((caddr_t)PS_STRINGS) - szsigcode - SPARE_USRSPACE);
+}
+
+
+static __inline void *
+stackgap_alloc(sgp, sz)
+ caddr_t *sgp;
+ size_t sz;
+{
+ void *p = (void *) *sgp;
+ *sgp += ALIGN(sz);
+ return p;
+}
+
+#ifdef DEBUG_LINUX
+#define DPRINTF(a) printf a;
+#else
+#define DPRINTF(a)
+#endif
+
+extern const char linux_emul_path[];
+
+int linux_emul_find __P((struct proc *, caddr_t *, const char *, char *,
+ char **, int));
+
+#define CHECKALTEXIST(p, sgp, path) \
+ linux_emul_find(p, sgp, linux_emul_path, path, &(path), 0)
+
+#define CHECKALTCREAT(p, sgp, path) \
+ linux_emul_find(p, sgp, linux_emul_path, path, &(path), 1)
+
+#endif /* !_LINUX_UTIL_H_ */