diff options
| author | Peter Wemm <peter@FreeBSD.org> | 1996-03-02 19:38:20 +0000 |
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 1996-03-02 19:38:20 +0000 |
| commit | d66a506616078adf4d266a309f979ffd95fe634f (patch) | |
| tree | 83b4d342a731e2a76c19f214d574f24753abe420 /sys/compat | |
| parent | 9a074e93b595e10edfd4c6fd6bdacc61879fe381 (diff) | |
Notes
Diffstat (limited to 'sys/compat')
| -rw-r--r-- | sys/compat/linux/linux_file.c | 397 | ||||
| -rw-r--r-- | sys/compat/linux/linux_ioctl.c | 47 | ||||
| -rw-r--r-- | sys/compat/linux/linux_ipc.c | 54 | ||||
| -rw-r--r-- | sys/compat/linux/linux_misc.c | 433 | ||||
| -rw-r--r-- | sys/compat/linux/linux_signal.c | 210 | ||||
| -rw-r--r-- | sys/compat/linux/linux_socket.c | 9 | ||||
| -rw-r--r-- | sys/compat/linux/linux_stats.c | 161 | ||||
| -rw-r--r-- | sys/compat/linux/linux_util.c | 179 | ||||
| -rw-r--r-- | sys/compat/linux/linux_util.h | 92 |
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_ */ |
