diff options
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_file.c | 945 | ||||
-rw-r--r-- | sys/compat/linux/linux_ioctl.c | 6 | ||||
-rw-r--r-- | sys/compat/linux/linux_ipc.c | 225 | ||||
-rw-r--r-- | sys/compat/linux/linux_ipc.h | 92 | ||||
-rw-r--r-- | sys/compat/linux/linux_mib.c | 2 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.c | 1309 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.c | 62 | ||||
-rw-r--r-- | sys/compat/linux/linux_signal.h | 8 | ||||
-rw-r--r-- | sys/compat/linux/linux_socket.c | 39 | ||||
-rw-r--r-- | sys/compat/linux/linux_stats.c | 336 | ||||
-rw-r--r-- | sys/compat/linux/linux_sysctl.c | 120 |
11 files changed, 1775 insertions, 1369 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 2a5d673..3d16a94 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -149,175 +149,6 @@ linux_open(struct proc *p, struct linux_open_args *args) return error; } -struct linux_flock { - short l_type; - short l_whence; - linux_off_t l_start; - linux_off_t l_len; - linux_pid_t l_pid; -}; - -static void -linux_to_bsd_flock(struct linux_flock *linux_flock, struct flock *bsd_flock) -{ - switch (linux_flock->l_type) { - case LINUX_F_RDLCK: - bsd_flock->l_type = F_RDLCK; - break; - case LINUX_F_WRLCK: - bsd_flock->l_type = F_WRLCK; - break; - case LINUX_F_UNLCK: - bsd_flock->l_type = F_UNLCK; - break; - default: - bsd_flock->l_type = -1; - break; - } - bsd_flock->l_whence = linux_flock->l_whence; - bsd_flock->l_start = (off_t)linux_flock->l_start; - bsd_flock->l_len = (off_t)linux_flock->l_len; - bsd_flock->l_pid = (pid_t)linux_flock->l_pid; -} - -static void -bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock) -{ - switch (bsd_flock->l_type) { - case F_RDLCK: - linux_flock->l_type = LINUX_F_RDLCK; - break; - case F_WRLCK: - linux_flock->l_type = LINUX_F_WRLCK; - break; - case F_UNLCK: - linux_flock->l_type = LINUX_F_UNLCK; - break; - } - linux_flock->l_whence = bsd_flock->l_whence; - linux_flock->l_start = (linux_off_t)bsd_flock->l_start; - linux_flock->l_len = (linux_off_t)bsd_flock->l_len; - linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid; -} - -int -linux_fcntl(struct proc *p, struct linux_fcntl_args *args) -{ - int error, result; - struct fcntl_args /* { - int fd; - int cmd; - long arg; - } */ fcntl_args; - struct linux_flock linux_flock; - struct flock *bsd_flock; - struct filedesc *fdp; - struct file *fp; - caddr_t sg; - - sg = stackgap_init(); - bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock)); - -#ifdef DEBUG - if (ldebug(fcntl)) - printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); -#endif - fcntl_args.fd = args->fd; - - switch (args->cmd) { - case LINUX_F_DUPFD: - fcntl_args.cmd = F_DUPFD; - fcntl_args.arg = args->arg; - return fcntl(p, &fcntl_args); - - case LINUX_F_GETFD: - fcntl_args.cmd = F_GETFD; - return fcntl(p, &fcntl_args); - - case LINUX_F_SETFD: - fcntl_args.cmd = F_SETFD; - fcntl_args.arg = args->arg; - return fcntl(p, &fcntl_args); - - case LINUX_F_GETFL: - fcntl_args.cmd = F_GETFL; - error = fcntl(p, &fcntl_args); - result = p->p_retval[0]; - p->p_retval[0] = 0; - if (result & O_RDONLY) p->p_retval[0] |= LINUX_O_RDONLY; - if (result & O_WRONLY) p->p_retval[0] |= LINUX_O_WRONLY; - if (result & O_RDWR) p->p_retval[0] |= LINUX_O_RDWR; - if (result & O_NDELAY) p->p_retval[0] |= LINUX_O_NONBLOCK; - if (result & O_APPEND) p->p_retval[0] |= LINUX_O_APPEND; - if (result & O_FSYNC) p->p_retval[0] |= LINUX_O_SYNC; - if (result & O_ASYNC) p->p_retval[0] |= LINUX_FASYNC; - return error; - - case LINUX_F_SETFL: - fcntl_args.arg = 0; - if (args->arg & LINUX_O_NDELAY) fcntl_args.arg |= O_NONBLOCK; - if (args->arg & LINUX_O_APPEND) fcntl_args.arg |= O_APPEND; - if (args->arg & LINUX_O_SYNC) fcntl_args.arg |= O_FSYNC; - if (args->arg & LINUX_FASYNC) fcntl_args.arg |= O_ASYNC; - fcntl_args.cmd = F_SETFL; - return fcntl(p, &fcntl_args); - - case LINUX_F_GETLK: - if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, - sizeof(struct linux_flock)))) - return error; - linux_to_bsd_flock(&linux_flock, bsd_flock); - fcntl_args.cmd = F_GETLK; - fcntl_args.arg = (long)bsd_flock; - error = fcntl(p, &fcntl_args); - if (error) - return error; - bsd_to_linux_flock(bsd_flock, &linux_flock); - return copyout((caddr_t)&linux_flock, (caddr_t)args->arg, - sizeof(struct linux_flock)); - - case LINUX_F_SETLK: - if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, - sizeof(struct linux_flock)))) - return error; - linux_to_bsd_flock(&linux_flock, bsd_flock); - fcntl_args.cmd = F_SETLK; - fcntl_args.arg = (long)bsd_flock; - return fcntl(p, &fcntl_args); - - case LINUX_F_SETLKW: - if ((error = copyin((caddr_t)args->arg, (caddr_t)&linux_flock, - sizeof(struct linux_flock)))) - return error; - linux_to_bsd_flock(&linux_flock, bsd_flock); - fcntl_args.cmd = F_SETLKW; - fcntl_args.arg = (long)bsd_flock; - return fcntl(p, &fcntl_args); - - case LINUX_F_GETOWN: - fcntl_args.cmd = F_GETOWN; - return fcntl(p, &fcntl_args); - - case LINUX_F_SETOWN: - /* - * XXX some Linux applications depend on F_SETOWN having no - * significant effect for pipes (SIGIO is not delivered for - * pipes under Linux-2.2.35 at least). - */ - 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_PIPE) - return EINVAL; - - fcntl_args.cmd = F_SETOWN; - fcntl_args.arg = args->arg; - return fcntl(p, &fcntl_args); - } - return EINVAL; -} - int linux_lseek(struct proc *p, struct linux_lseek_args *args) { @@ -333,7 +164,7 @@ linux_lseek(struct proc *p, struct linux_lseek_args *args) #ifdef DEBUG if (ldebug(lseek)) printf(ARGS(lseek, "%d, %ld, %d"), - args->fdes, args->off, args->whence); + args->fdes, (long)args->off, args->whence); #endif tmp_args.fd = args->fdes; tmp_args.offset = (off_t)args->off; @@ -372,17 +203,6 @@ linux_llseek(struct proc *p, struct linux_llseek_args *args) } #endif /*!__alpha__*/ - -struct linux_dirent { - long dino; - linux_off_t doff; - unsigned short dreclen; - char dname[LINUX_NAME_MAX + 1]; -}; - -#define LINUX_RECLEN(de,namlen) \ - ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1)) - #ifndef __alpha__ int linux_readdir(struct proc *p, struct linux_readdir_args *args) @@ -396,178 +216,250 @@ linux_readdir(struct proc *p, struct linux_readdir_args *args) } #endif /*!__alpha__*/ -int -linux_getdents(struct proc *p, struct linux_getdents_args *args) -{ - register struct dirent *bdp; - struct vnode *vp; - caddr_t inp, buf; /* BSD-format */ - int len, reclen; /* BSD-format */ - caddr_t outp; /* Linux-format */ - int resid, linuxreclen=0; /* Linux-format */ - struct file *fp; - struct uio auio; - struct iovec aiov; - struct vattr va; - off_t off; - struct linux_dirent linux_dirent; - int buflen, error, eofflag, nbytes, justone; - u_long *cookies = NULL, *cookiep; - int ncookies; +/* + * Note that linux_getdents(2) and linux_getdents64(2) have the same + * arguments. They only differ in the definition of struct dirent they + * operate on. We use this to common the code, with the exception of + * accessing struct dirent. Note that linux_readdir(2) is implemented + * by means of linux_getdents(2). In this case we never operate on + * struct dirent64 and thus don't need to handle it... + */ -#ifdef DEBUG - if (ldebug(getdents)) - printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); -#endif - if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { - return (error); - } +struct l_dirent { + l_long d_ino; + l_off_t d_off; + l_ushort d_reclen; + char d_name[LINUX_NAME_MAX + 1]; +}; - if ((fp->f_flag & FREAD) == 0) - return (EBADF); +struct l_dirent64 { + uint64_t d_ino; + int64_t d_off; + l_ushort d_reclen; + u_char d_type; + char d_name[LINUX_NAME_MAX + 1]; +}; - vp = (struct vnode *) fp->f_data; +#define LINUX_RECLEN(de,namlen) \ + ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) - if (vp->v_type != VDIR) - return (EINVAL); +#define LINUX_DIRBLKSIZ 512 - if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { - return error; - } +static int +getdents_common(struct proc *p, struct linux_getdents64_args *args, + int is64bit) +{ + register struct dirent *bdp; + struct vnode *vp; + caddr_t inp, buf; /* BSD-format */ + int len, reclen; /* BSD-format */ + caddr_t outp; /* Linux-format */ + int resid, linuxreclen=0; /* Linux-format */ + struct file *fp; + struct uio auio; + struct iovec aiov; + struct vattr va; + off_t off; + struct l_dirent linux_dirent; + struct l_dirent64 linux_dirent64; + int buflen, error, eofflag, nbytes, justone; + u_long *cookies = NULL, *cookiep; + int ncookies; + + if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) + return (error); + + if ((fp->f_flag & FREAD) == 0) + return (EBADF); + + vp = (struct vnode *) fp->f_data; + if (vp->v_type != VDIR) + return (EINVAL); + + if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) + return (error); + + nbytes = args->count; + if (nbytes == 1) { + /* readdir(2) case. Always struct dirent. */ + if (is64bit) + return (EINVAL); + nbytes = sizeof(linux_dirent); + justone = 1; + } else + justone = 0; + + off = fp->f_offset; + + buflen = max(LINUX_DIRBLKSIZ, nbytes); + buflen = min(buflen, MAXBSIZE); + buf = malloc(buflen, M_TEMP, M_WAITOK); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - nbytes = args->count; - if (nbytes == 1) { - nbytes = sizeof (struct linux_dirent); - justone = 1; - } - else - justone = 0; - - off = fp->f_offset; -#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ - buflen = max(DIRBLKSIZ, nbytes); - buflen = min(buflen, MAXBSIZE); - buf = malloc(buflen, M_TEMP, M_WAITOK); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); again: - aiov.iov_base = buf; - aiov.iov_len = buflen; - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_SYSSPACE; - auio.uio_procp = p; - auio.uio_resid = buflen; - auio.uio_offset = off; - - if (cookies) { - free(cookies, M_TEMP); - cookies = NULL; - } - - error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies); - if (error) { - goto out; - } - - inp = buf; - outp = (caddr_t) args->dent; - resid = nbytes; - if ((len = buflen - auio.uio_resid) <= 0) { - goto eof; - } - - cookiep = cookies; - - if (cookies) { - /* - * When using cookies, the vfs has the option of reading from - * a different offset than that supplied (UFS truncates the - * offset to a block boundary to make sure that it never reads - * partway through a directory entry, even if the directory - * has been compacted). - */ - while (len > 0 && ncookies > 0 && *cookiep <= off) { - bdp = (struct dirent *) inp; - len -= bdp->d_reclen; - inp += bdp->d_reclen; - cookiep++; - ncookies--; - } - } - - while (len > 0) { - if (cookiep && ncookies == 0) - break; - bdp = (struct dirent *) inp; - reclen = bdp->d_reclen; - if (reclen & 3) { - printf("linux_readdir: reclen=%d\n", reclen); - error = EFAULT; - goto out; - } - - if (bdp->d_fileno == 0) { - inp += reclen; - if (cookiep) { - off = *cookiep++; - ncookies--; - } else - off += reclen; - len -= reclen; - continue; - } - linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); - if (reclen > len || resid < linuxreclen) { - outp++; - break; + aiov.iov_base = buf; + aiov.iov_len = buflen; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_procp = p; + auio.uio_resid = buflen; + auio.uio_offset = off; + + if (cookies) { + free(cookies, M_TEMP); + cookies = NULL; } - linux_dirent.dino = (long) bdp->d_fileno; - if (justone) { - /* - * old linux-style readdir usage. - */ - linux_dirent.doff = (linux_off_t) linuxreclen; - linux_dirent.dreclen = (u_short) bdp->d_namlen; - } else { - if (cookiep) - linux_dirent.doff = (linux_off_t)*cookiep; - else - linux_dirent.doff = (linux_off_t)(off + reclen); - linux_dirent.dreclen = (u_short) linuxreclen; + + if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, + &cookies))) + goto out; + + inp = buf; + outp = (caddr_t)args->dirent; + resid = nbytes; + if ((len = buflen - auio.uio_resid) <= 0) + goto eof; + + cookiep = cookies; + + if (cookies) { + /* + * When using cookies, the vfs has the option of reading from + * a different offset than that supplied (UFS truncates the + * offset to a block boundary to make sure that it never reads + * partway through a directory entry, even if the directory + * has been compacted). + */ + while (len > 0 && ncookies > 0 && *cookiep <= off) { + bdp = (struct dirent *) inp; + len -= bdp->d_reclen; + inp += bdp->d_reclen; + cookiep++; + ncookies--; + } } - strcpy(linux_dirent.dname, bdp->d_name); - if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { - goto out; + + while (len > 0) { + if (cookiep && ncookies == 0) + break; + bdp = (struct dirent *) inp; + reclen = bdp->d_reclen; + if (reclen & 3) { + error = EFAULT; + goto out; + } + + if (bdp->d_fileno == 0) { + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + + len -= reclen; + continue; + } + + linuxreclen = (is64bit) + ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) + : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); + + if (reclen > len || resid < linuxreclen) { + outp++; + break; + } + + if (justone) { + /* readdir(2) case. */ + linux_dirent.d_ino = (l_long)bdp->d_fileno; + linux_dirent.d_off = (l_off_t)linuxreclen; + linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; + strcpy(linux_dirent.d_name, bdp->d_name); + error = copyout(&linux_dirent, outp, linuxreclen); + } else { + if (is64bit) { + linux_dirent64.d_ino = bdp->d_fileno; + linux_dirent64.d_off = (cookiep) + ? (l_off_t)*cookiep + : (l_off_t)(off + reclen); + linux_dirent64.d_reclen = + (l_ushort)linuxreclen; + linux_dirent64.d_type = bdp->d_type; + strcpy(linux_dirent64.d_name, bdp->d_name); + error = copyout(&linux_dirent64, outp, + linuxreclen); + } else { + linux_dirent.d_ino = bdp->d_fileno; + linux_dirent.d_off = (cookiep) + ? (l_off_t)*cookiep + : (l_off_t)(off + reclen); + linux_dirent.d_reclen = (l_ushort)linuxreclen; + strcpy(linux_dirent.d_name, bdp->d_name); + error = copyout(&linux_dirent, outp, + linuxreclen); + } + } + if (error) + goto out; + + inp += reclen; + if (cookiep) { + off = *cookiep++; + ncookies--; + } else + off += reclen; + + outp += linuxreclen; + resid -= linuxreclen; + len -= reclen; + if (justone) + break; } - inp += reclen; - if (cookiep) { - off = *cookiep++; - ncookies--; - } else - off += reclen; - outp += linuxreclen; - resid -= linuxreclen; - len -= reclen; - if (justone) - break; - } - if (outp == (caddr_t) args->dent) - goto again; - fp->f_offset = off; + if (outp == (caddr_t)args->dirent) + goto again; - if (justone) - nbytes = resid + linuxreclen; + fp->f_offset = off; + if (justone) + nbytes = resid + linuxreclen; eof: - p->p_retval[0] = nbytes - resid; + p->p_retval[0] = nbytes - resid; + out: - if (cookies) - free(cookies, M_TEMP); - VOP_UNLOCK(vp, 0, p); - free(buf, M_TEMP); - return error; + if (cookies) + free(cookies, M_TEMP); + + VOP_UNLOCK(vp, 0, p); + free(buf, M_TEMP); + return (error); +} + +int +linux_getdents(struct proc *p, struct linux_getdents_args *args) +{ + +#ifdef DEBUG + if (ldebug(getdents)) + printf(ARGS(getdents, "%d, *, %d"), args->fd, args->count); +#endif + + return (getdents_common(p, (struct linux_getdents64_args*)args, 0)); +} + +int +linux_getdents64(struct proc *p, struct linux_getdents64_args *args) +{ + +#ifdef DEBUG + if (ldebug(getdents64)) + printf(ARGS(getdents64, "%d, *, %d"), args->fd, args->count); +#endif + + return (getdents_common(p, args, 1)); } /* @@ -649,50 +541,6 @@ linux_chmod(struct proc *p, struct linux_chmod_args *args) } int -linux_chown(struct proc *p, struct linux_chown_args *args) -{ - struct chown_args bsd; - caddr_t sg; - - sg = stackgap_init(); - CHECKALTEXIST(p, &sg, args->path); - -#ifdef DEBUG - if (ldebug(chown)) - printf(ARGS(chown, "%s, %d, %d"), - 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); -} - -int -linux_lchown(struct proc *p, struct linux_lchown_args *args) -{ - struct lchown_args bsd; - caddr_t sg; - - sg = stackgap_init(); - CHECKALTEXIST(p, &sg, args->path); - -#ifdef DEBUG - if (ldebug(lchown)) - printf(ARGS(lchown, "%s, %d, %d"), - args->path, args->uid, args->gid); -#endif - bsd.path = args->path; - /* XXX size casts here */ - bsd.uid = args->uid; - bsd.gid = args->gid; - - return lchown(p, &bsd); -} - -int linux_mkdir(struct proc *p, struct linux_mkdir_args *args) { struct mkdir_args bsd; @@ -801,7 +649,8 @@ linux_truncate(struct proc *p, struct linux_truncate_args *args) #ifdef DEBUG if (ldebug(truncate)) - printf(ARGS(truncate, "%s, %ld"), args->path, args->length); + printf(ARGS(truncate, "%s, %ld"), args->path, + (long)args->length); #endif bsd.path = args->path; bsd.length = args->length; @@ -937,17 +786,17 @@ linux_mount(struct proc *p, struct linux_mount_args *args) } int -linux_umount(struct proc *p, struct linux_umount_args *args) +linux_oldumount(struct proc *p, struct linux_oldumount_args *args) { - struct linux_umount2_args args2; + struct linux_umount_args args2; args2.path = args->path; args2.flags = 0; - return (linux_umount2(p, &args2)); + return (linux_umount(p, &args2)); } int -linux_umount2(struct proc *p, struct linux_umount2_args *args) +linux_umount(struct proc *p, struct linux_umount_args *args) { struct unmount_args bsd; @@ -955,3 +804,325 @@ linux_umount2(struct proc *p, struct linux_umount2_args *args) bsd.flags = args->flags; /* XXX correct? */ return (unmount(p, &bsd)); } + +/* + * fcntl family of syscalls + */ + +struct l_flock { + l_short l_type; + l_short l_whence; + l_off_t l_start; + l_off_t l_len; + l_pid_t l_pid; +}; + +static void +linux_to_bsd_flock(struct l_flock *linux_flock, struct flock *bsd_flock) +{ + switch (linux_flock->l_type) { + case LINUX_F_RDLCK: + bsd_flock->l_type = F_RDLCK; + break; + case LINUX_F_WRLCK: + bsd_flock->l_type = F_WRLCK; + break; + case LINUX_F_UNLCK: + bsd_flock->l_type = F_UNLCK; + break; + default: + bsd_flock->l_type = -1; + break; + } + bsd_flock->l_whence = linux_flock->l_whence; + bsd_flock->l_start = (off_t)linux_flock->l_start; + bsd_flock->l_len = (off_t)linux_flock->l_len; + bsd_flock->l_pid = (pid_t)linux_flock->l_pid; +} + +static void +bsd_to_linux_flock(struct flock *bsd_flock, struct l_flock *linux_flock) +{ + switch (bsd_flock->l_type) { + case F_RDLCK: + linux_flock->l_type = LINUX_F_RDLCK; + break; + case F_WRLCK: + linux_flock->l_type = LINUX_F_WRLCK; + break; + case F_UNLCK: + linux_flock->l_type = LINUX_F_UNLCK; + break; + } + linux_flock->l_whence = bsd_flock->l_whence; + linux_flock->l_start = (l_off_t)bsd_flock->l_start; + linux_flock->l_len = (l_off_t)bsd_flock->l_len; + linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; +} + +#if defined(__i386__) +struct l_flock64 { + l_short l_type; + l_short l_whence; + l_loff_t l_start; + l_loff_t l_len; + l_pid_t l_pid; +}; + +static void +linux_to_bsd_flock64(struct l_flock64 *linux_flock, struct flock *bsd_flock) +{ + switch (linux_flock->l_type) { + case LINUX_F_RDLCK: + bsd_flock->l_type = F_RDLCK; + break; + case LINUX_F_WRLCK: + bsd_flock->l_type = F_WRLCK; + break; + case LINUX_F_UNLCK: + bsd_flock->l_type = F_UNLCK; + break; + default: + bsd_flock->l_type = -1; + break; + } + bsd_flock->l_whence = linux_flock->l_whence; + bsd_flock->l_start = (off_t)linux_flock->l_start; + bsd_flock->l_len = (off_t)linux_flock->l_len; + bsd_flock->l_pid = (pid_t)linux_flock->l_pid; +} + +static void +bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) +{ + switch (bsd_flock->l_type) { + case F_RDLCK: + linux_flock->l_type = LINUX_F_RDLCK; + break; + case F_WRLCK: + linux_flock->l_type = LINUX_F_WRLCK; + break; + case F_UNLCK: + linux_flock->l_type = LINUX_F_UNLCK; + break; + } + linux_flock->l_whence = bsd_flock->l_whence; + linux_flock->l_start = (l_loff_t)bsd_flock->l_start; + linux_flock->l_len = (l_loff_t)bsd_flock->l_len; + linux_flock->l_pid = (l_pid_t)bsd_flock->l_pid; +} +#endif /* __i386__ */ + +#if defined(__alpha__) +#define linux_fcntl64_args linux_fcntl_args +#endif + +static int +fcntl_common(struct proc *p, struct linux_fcntl64_args *args) +{ + struct fcntl_args fcntl_args; + struct filedesc *fdp; + struct file *fp; + int error, result; + + fcntl_args.fd = args->fd; + + switch (args->cmd) { + case LINUX_F_DUPFD: + fcntl_args.cmd = F_DUPFD; + fcntl_args.arg = args->arg; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_GETFD: + fcntl_args.cmd = F_GETFD; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_SETFD: + fcntl_args.cmd = F_SETFD; + fcntl_args.arg = args->arg; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_GETFL: + fcntl_args.cmd = F_GETFL; + error = fcntl(p, &fcntl_args); + result = p->p_retval[0]; + p->p_retval[0] = 0; + if (result & O_RDONLY) + p->p_retval[0] |= LINUX_O_RDONLY; + if (result & O_WRONLY) + p->p_retval[0] |= LINUX_O_WRONLY; + if (result & O_RDWR) + p->p_retval[0] |= LINUX_O_RDWR; + if (result & O_NDELAY) + p->p_retval[0] |= LINUX_O_NONBLOCK; + if (result & O_APPEND) + p->p_retval[0] |= LINUX_O_APPEND; + if (result & O_FSYNC) + p->p_retval[0] |= LINUX_O_SYNC; + if (result & O_ASYNC) + p->p_retval[0] |= LINUX_FASYNC; + return (error); + + case LINUX_F_SETFL: + fcntl_args.arg = 0; + if (args->arg & LINUX_O_NDELAY) + fcntl_args.arg |= O_NONBLOCK; + if (args->arg & LINUX_O_APPEND) + fcntl_args.arg |= O_APPEND; + if (args->arg & LINUX_O_SYNC) + fcntl_args.arg |= O_FSYNC; + if (args->arg & LINUX_FASYNC) + fcntl_args.arg |= O_ASYNC; + fcntl_args.cmd = F_SETFL; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_GETOWN: + fcntl_args.cmd = F_GETOWN; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_SETOWN: + /* + * XXX some Linux applications depend on F_SETOWN having no + * significant effect for pipes (SIGIO is not delivered for + * pipes under Linux-2.2.35 at least). + */ + 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_PIPE) + return (EINVAL); + + fcntl_args.cmd = F_SETOWN; + fcntl_args.arg = args->arg; + return (fcntl(p, &fcntl_args)); + } + + return (EINVAL); +} + +int +linux_fcntl(struct proc *p, struct linux_fcntl_args *args) +{ + struct linux_fcntl64_args args64; + struct fcntl_args fcntl_args; + struct l_flock linux_flock; + struct flock *bsd_flock; + int error; + caddr_t sg; + + sg = stackgap_init(); + bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); + +#ifdef DEBUG + if (ldebug(fcntl)) + printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); +#endif + + switch (args->cmd) { + case LINUX_F_GETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_GETLK; + fcntl_args.arg = (long)bsd_flock; + error = fcntl(p, &fcntl_args); + if (error) + return (error); + bsd_to_linux_flock(bsd_flock, &linux_flock); + return (copyout(&linux_flock, (caddr_t)args->arg, + sizeof(linux_flock))); + + case LINUX_F_SETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLK; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_SETLKW: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLKW; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(p, &fcntl_args)); + } + + args64.fd = args->fd; + args64.cmd = args->cmd; + args64.arg = args->arg; + return (fcntl_common(p, &args64)); +} + +#if defined(__i386__) +int +linux_fcntl64(struct proc *p, struct linux_fcntl64_args *args) +{ + struct fcntl_args fcntl_args; + struct l_flock64 linux_flock; + struct flock *bsd_flock; + int error; + caddr_t sg; + + sg = stackgap_init(); + bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(bsd_flock)); + +#ifdef DEBUG + if (ldebug(fcntl64)) + printf(ARGS(fcntl64, "%d, %08x, *"), args->fd, args->cmd); +#endif + + switch (args->cmd) { + case LINUX_F_GETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_GETLK; + fcntl_args.arg = (long)bsd_flock; + error = fcntl(p, &fcntl_args); + if (error) + return (error); + bsd_to_linux_flock64(bsd_flock, &linux_flock); + return (copyout(&linux_flock, (caddr_t)args->arg, + sizeof(linux_flock))); + + case LINUX_F_SETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLK; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(p, &fcntl_args)); + + case LINUX_F_SETLKW: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock64(&linux_flock, bsd_flock); + fcntl_args.fd = args->fd; + fcntl_args.cmd = F_SETLKW; + fcntl_args.arg = (long)bsd_flock; + return (fcntl(p, &fcntl_args)); + } + + return (fcntl_common(p, args)); +} +#endif /* __i386__ */ diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 2079fcd..b4fc8ce 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -1379,7 +1379,7 @@ linux_ioctl_socket(struct proc *p, struct linux_ioctl_args *args) struct ifnet *ifp; struct ifaddr *ifa; struct sockaddr_dl *sdl; - struct linux_ifreq *ifr = (struct linux_ifreq *)args->arg; + struct l_ifreq *ifr = (struct l_ifreq *)args->arg; /* Note that we don't actually respect the name in the ifreq * structure, as Linux interface names are all different. @@ -1424,7 +1424,7 @@ linux_ioctl_socket(struct proc *p, struct linux_ioctl_args *args) int linux_ioctl(struct proc *p, struct linux_ioctl_args *args) { - struct filedesc *fdp = p->p_fd; + struct filedesc *fdp; struct file *fp; struct handler_element *he; int error, cmd; @@ -1434,9 +1434,9 @@ linux_ioctl(struct proc *p, struct linux_ioctl_args *args) printf(ARGS(ioctl, "%d, %04lx, *"), args->fd, args->cmd); #endif + fdp = p->p_fd; if ((unsigned)args->fd >= fdp->fd_nfiles) return (EBADF); - fp = fdp->fd_ofiles[args->fd]; if (fp == NULL || (fp->f_flag & (FREAD|FWRITE)) == 0) return (EBADF); diff --git a/sys/compat/linux/linux_ipc.c b/sys/compat/linux/linux_ipc.c index e68580f..de9b47a 100644 --- a/sys/compat/linux/linux_ipc.c +++ b/sys/compat/linux/linux_ipc.c @@ -40,18 +40,18 @@ #include <compat/linux/linux_ipc.h> #include <compat/linux/linux_util.h> -struct linux_ipc_perm { - linux_key_t key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; +struct l_ipc_perm { + l_key_t key; + l_uid16_t uid; + l_gid16_t gid; + l_uid16_t cuid; + l_gid16_t cgid; + l_ushort mode; + l_ushort seq; }; static void -linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) +linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp) { bpp->key = lpp->key; bpp->uid = lpp->uid; @@ -64,7 +64,7 @@ linux_to_bsd_ipc_perm(struct linux_ipc_perm *lpp, struct ipc_perm *bpp) static void -bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) +bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp) { lpp->key = bpp->key; lpp->uid = bpp->uid; @@ -75,33 +75,33 @@ bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct linux_ipc_perm *lpp) lpp->seq = bpp->seq; } -struct linux_semid_ds { - struct linux_ipc_perm sem_perm; - linux_time_t sem_otime; - linux_time_t sem_ctime; +struct l_semid_ds { + struct l_ipc_perm sem_perm; + l_time_t sem_otime; + l_time_t sem_ctime; void *sem_base; void *sem_pending; void *sem_pending_last; void *undo; - ushort sem_nsems; + l_ushort sem_nsems; }; -struct linux_shmid_ds { - struct linux_ipc_perm shm_perm; - int shm_segsz; - linux_time_t shm_atime; - linux_time_t shm_dtime; - linux_time_t shm_ctime; - ushort shm_cpid; - ushort shm_lpid; - short shm_nattch; - ushort private1; - void *private2; - void *private3; +struct l_shmid_ds { + struct l_ipc_perm shm_perm; + l_int shm_segsz; + l_time_t shm_atime; + l_time_t shm_dtime; + l_time_t shm_ctime; + l_ushort shm_cpid; + l_ushort shm_lpid; + l_short shm_nattch; + l_ushort private1; + void *private2; + void *private3; }; static void -linux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp) +linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->sem_perm, &bsp->sem_perm); bsp->sem_otime = lsp->sem_otime; @@ -111,7 +111,7 @@ linux_to_bsd_semid_ds(struct linux_semid_ds *lsp, struct semid_ds *bsp) } static void -bsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp) +bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm); lsp->sem_otime = bsp->sem_otime; @@ -121,7 +121,7 @@ bsd_to_linux_semid_ds(struct semid_ds *bsp, struct linux_semid_ds *lsp) } static void -linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) +linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp) { linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm); bsp->shm_segsz = lsp->shm_segsz; @@ -135,7 +135,7 @@ linux_to_bsd_shmid_ds(struct linux_shmid_ds *lsp, struct shmid_ds *bsp) } static void -bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct linux_shmid_ds *lsp) +bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp) { bsd_to_linux_ipc_perm(&bsp->shm_perm, &lsp->shm_perm); lsp->shm_segsz = bsp->shm_segsz; @@ -157,9 +157,9 @@ linux_semop(struct proc *p, struct linux_semop_args *args) int nsops; } */ bsd_args; - bsd_args.semid = args->arg1; - bsd_args.sops = (struct sembuf *)args->ptr; - bsd_args.nsops = args->arg2; + bsd_args.semid = args->semid; + bsd_args.sops = (struct sembuf *)args->tsops; + bsd_args.nsops = args->nsops; return semop(p, &bsd_args); } @@ -172,33 +172,32 @@ linux_semget(struct proc *p, struct linux_semget_args *args) int semflg; } */ bsd_args; - bsd_args.key = args->arg1; - bsd_args.nsems = args->arg2; - bsd_args.semflg = args->arg3; + bsd_args.key = args->key; + bsd_args.nsems = args->nsems; + bsd_args.semflg = args->semflg; return semget(p, &bsd_args); } int linux_semctl(struct proc *p, struct linux_semctl_args *args) { - struct linux_semid_ds linux_semid; - struct semid_ds bsd_semid; + struct l_semid_ds linux_semid; struct __semctl_args /* { - int semid; - int semnum; - int cmd; - union semun *arg; + int semid; + int semnum; + int cmd; + union semun *arg; } */ bsd_args; - int error; - caddr_t sg, unptr, dsp, ldsp; + int error; + union semun *unptr; + caddr_t sg; sg = stackgap_init(); - bsd_args.semid = args->arg1; - bsd_args.semnum = args->arg2; - bsd_args.cmd = args->arg3; - bsd_args.arg = (union semun *)args->ptr; + bsd_args.semid = args->semid; + bsd_args.semnum = args->semnum; + bsd_args.arg = (union semun *)&args->arg; - switch (args->arg3) { + switch (args->cmd) { case LINUX_IPC_RMID: bsd_args.cmd = IPC_RMID; break; @@ -219,48 +218,32 @@ linux_semctl(struct proc *p, struct linux_semctl_args *args) break; case LINUX_IPC_SET: bsd_args.cmd = IPC_SET; - error = copyin(args->ptr, &ldsp, sizeof(ldsp)); + error = copyin((caddr_t)args->arg.buf, &linux_semid, + sizeof(linux_semid)); if (error) - return error; - error = copyin(ldsp, (caddr_t)&linux_semid, sizeof(linux_semid)); - if (error) - return error; - linux_to_bsd_semid_ds(&linux_semid, &bsd_semid); + return (error); unptr = stackgap_alloc(&sg, sizeof(union semun)); - dsp = stackgap_alloc(&sg, sizeof(struct semid_ds)); - error = copyout((caddr_t)&bsd_semid, dsp, sizeof(bsd_semid)); - if (error) - return error; - error = copyout((caddr_t)&dsp, unptr, sizeof(dsp)); - if (error) - return error; - bsd_args.arg = (union semun *)unptr; + unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds)); + linux_to_bsd_semid_ds(&linux_semid, unptr->buf); + bsd_args.arg = unptr; return __semctl(p, &bsd_args); case LINUX_IPC_STAT: bsd_args.cmd = IPC_STAT; - unptr = stackgap_alloc(&sg, sizeof(union semun *)); - dsp = stackgap_alloc(&sg, sizeof(struct semid_ds)); - error = copyout((caddr_t)&dsp, unptr, sizeof(dsp)); - if (error) - return error; - bsd_args.arg = (union semun *)unptr; + unptr = stackgap_alloc(&sg, sizeof(union semun)); + unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds)); + bsd_args.arg = unptr; error = __semctl(p, &bsd_args); if (error) return error; - error = copyin(dsp, (caddr_t)&bsd_semid, sizeof(bsd_semid)); - if (error) - return error; - bsd_to_linux_semid_ds(&bsd_semid, &linux_semid); - error = copyin(args->ptr, &ldsp, sizeof(ldsp)); - if (error) - return error; - return copyout((caddr_t)&linux_semid, ldsp, sizeof(linux_semid)); + bsd_to_linux_semid_ds(unptr->buf, &linux_semid); + return copyout(&linux_semid, (caddr_t)args->arg.buf, + sizeof(linux_semid)); case LINUX_GETALL: /* FALLTHROUGH */ case LINUX_SETALL: /* FALLTHROUGH */ default: - uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->arg3); + uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd); return EINVAL; } return __semctl(p, &bsd_args); @@ -276,10 +259,10 @@ linux_msgsnd(struct proc *p, struct linux_msgsnd_args *args) int msgflg; } */ bsd_args; - bsd_args.msqid = args->arg1; - bsd_args.msgp = args->ptr; - bsd_args.msgsz = args->arg2; - bsd_args.msgflg = args->arg3; + bsd_args.msqid = args->msqid; + bsd_args.msgp = args->msgp; + bsd_args.msgsz = args->msgsz; + bsd_args.msgflg = args->msgflg; return msgsnd(p, &bsd_args); } @@ -294,11 +277,11 @@ linux_msgrcv(struct proc *p, struct linux_msgrcv_args *args) int msgflg; } */ bsd_args; - bsd_args.msqid = args->arg1; - bsd_args.msgp = args->ptr; - bsd_args.msgsz = args->arg2; - bsd_args.msgtyp = 0; - bsd_args.msgflg = args->arg3; + bsd_args.msqid = args->msqid; + bsd_args.msgp = args->msgp; + bsd_args.msgsz = args->msgsz; + bsd_args.msgtyp = 0; /* XXX - args->msgtyp; */ + bsd_args.msgflg = args->msgflg; return msgrcv(p, &bsd_args); } @@ -310,8 +293,8 @@ linux_msgget(struct proc *p, struct linux_msgget_args *args) int msgflg; } */ bsd_args; - bsd_args.key = args->arg1; - bsd_args.msgflg = args->arg2; + bsd_args.key = args->key; + bsd_args.msgflg = args->msgflg; return msgget(p, &bsd_args); } @@ -325,11 +308,11 @@ linux_msgctl(struct proc *p, struct linux_msgctl_args *args) } */ bsd_args; int error; - bsd_args.msqid = args->arg1; - bsd_args.cmd = args->arg2; - bsd_args.buf = (struct msqid_ds *)args->ptr; + bsd_args.msqid = args->msqid; + bsd_args.cmd = args->cmd; + bsd_args.buf = (struct msqid_ds *)args->buf; error = msgctl(p, &bsd_args); - return ((args->arg2 == LINUX_IPC_RMID && error == EINVAL) ? 0 : error); + return ((args->cmd == LINUX_IPC_RMID && error == EINVAL) ? 0 : error); } int @@ -342,13 +325,13 @@ linux_shmat(struct proc *p, struct linux_shmat_args *args) } */ bsd_args; int error; - bsd_args.shmid = args->arg1; - bsd_args.shmaddr = args->ptr; - bsd_args.shmflg = args->arg2; + bsd_args.shmid = args->shmid; + bsd_args.shmaddr = args->shmaddr; + bsd_args.shmflg = args->shmflg; if ((error = shmat(p, &bsd_args))) return error; #ifdef __i386__ - if ((error = copyout(p->p_retval, (caddr_t)args->arg3, sizeof(int)))) + if ((error = copyout(p->p_retval, (caddr_t)args->raddr, sizeof(l_ulong)))) return error; p->p_retval[0] = 0; #endif @@ -362,7 +345,7 @@ linux_shmdt(struct proc *p, struct linux_shmdt_args *args) void *shmaddr; } */ bsd_args; - bsd_args.shmaddr = args->ptr; + bsd_args.shmaddr = args->shmaddr; return shmdt(p, &bsd_args); } @@ -375,17 +358,16 @@ linux_shmget(struct proc *p, struct linux_shmget_args *args) int shmflg; } */ bsd_args; - bsd_args.key = args->arg1; - bsd_args.size = args->arg2; - bsd_args.shmflg = args->arg3; + bsd_args.key = args->key; + bsd_args.size = args->size; + bsd_args.shmflg = args->shmflg; return shmget(p, &bsd_args); } int linux_shmctl(struct proc *p, struct linux_shmctl_args *args) { - struct shmid_ds bsd_shmid; - struct linux_shmid_ds linux_shmid; + struct l_shmid_ds linux_shmid; struct shmctl_args /* { int shmid; int cmd; @@ -394,46 +376,37 @@ linux_shmctl(struct proc *p, struct linux_shmctl_args *args) int error; caddr_t sg = stackgap_init(); - switch (args->arg2) { + switch (args->cmd) { case LINUX_IPC_STAT: - bsd_args.shmid = args->arg1; + bsd_args.shmid = args->shmid; bsd_args.cmd = IPC_STAT; bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds)); if ((error = shmctl(p, &bsd_args))) return error; - if ((error = copyin((caddr_t)bsd_args.buf, (caddr_t)&bsd_shmid, - sizeof(struct shmid_ds)))) - return error; - bsd_to_linux_shmid_ds(&bsd_shmid, &linux_shmid); - return copyout((caddr_t)&linux_shmid, args->ptr, sizeof(linux_shmid)); + bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid); + return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid)); case LINUX_IPC_SET: - if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, - sizeof(linux_shmid)))) + if ((error = copyin((caddr_t)args->buf, &linux_shmid, + sizeof(linux_shmid)))) return error; - linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 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; - bsd_args.shmid = args->arg1; + linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf); + bsd_args.shmid = args->shmid; bsd_args.cmd = IPC_SET; return shmctl(p, &bsd_args); case LINUX_IPC_RMID: - bsd_args.shmid = args->arg1; + bsd_args.shmid = args->shmid; bsd_args.cmd = IPC_RMID; - if (NULL == args->ptr) + if (args->buf == NULL) bsd_args.buf = NULL; else { - if ((error = copyin(args->ptr, (caddr_t)&linux_shmid, + if ((error = copyin((caddr_t)args->buf, &linux_shmid, sizeof(linux_shmid)))) return error; - linux_to_bsd_shmid_ds(&linux_shmid, &bsd_shmid); 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; + linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf); } return shmctl(p, &bsd_args); @@ -443,7 +416,7 @@ linux_shmctl(struct proc *p, struct linux_shmctl_args *args) case LINUX_SHM_LOCK: case LINUX_SHM_UNLOCK: default: - uprintf("LINUX: 'ipc' typ=%d not implemented\n", args->arg2); + uprintf("linux: 'ipc' typ=%d not implemented\n", args->cmd); return EINVAL; } } diff --git a/sys/compat/linux/linux_ipc.h b/sys/compat/linux/linux_ipc.h index 946d963..d0db461 100644 --- a/sys/compat/linux/linux_ipc.h +++ b/sys/compat/linux/linux_ipc.h @@ -31,21 +31,86 @@ #ifndef _LINUX_IPC_H_ #define _LINUX_IPC_H_ -#ifndef __alpha__ +#ifdef __i386__ -#define linux_msgctl_args linux_ipc_args -#define linux_msgget_args linux_ipc_args -#define linux_msgrcv_args linux_ipc_args -#define linux_msgsnd_args linux_ipc_args +struct linux_msgctl_args +{ + l_int msqid; + l_int cmd; + struct l_msqid_ds *buf; +}; -#define linux_semctl_args linux_ipc_args -#define linux_semget_args linux_ipc_args -#define linux_semop_args linux_ipc_args +struct linux_msgget_args +{ + l_key_t key; + l_int msgflg; +}; -#define linux_shmat_args linux_ipc_args -#define linux_shmctl_args linux_ipc_args -#define linux_shmdt_args linux_ipc_args -#define linux_shmget_args linux_ipc_args +struct linux_msgrcv_args +{ + l_int msqid; + struct l_msgbuf *msgp; + l_size_t msgsz; + l_long msgtyp; + l_int msgflg; +}; + +struct linux_msgsnd_args +{ + l_int msqid; + struct l_msgbuf *msgp; + l_size_t msgsz; + l_int msgflg; +}; + +struct linux_semctl_args +{ + l_int semid; + l_int semnum; + l_int cmd; + union l_semun arg; +}; + +struct linux_semget_args +{ + l_key_t key; + l_int nsems; + l_int semflg; +}; + +struct linux_semop_args +{ + l_int semid; + struct l_sembuf *tsops; + l_uint nsops; +}; + +struct linux_shmat_args +{ + l_int shmid; + char *shmaddr; + l_int shmflg; + l_ulong *raddr; +}; + +struct linux_shmctl_args +{ + l_int shmid; + l_int cmd; + struct l_shmid_ds *buf; +}; + +struct linux_shmdt_args +{ + char *shmaddr; +}; + +struct linux_shmget_args +{ + l_key_t key; + l_size_t size; + l_int shmflg; +}; int linux_msgctl __P((struct proc *, struct linux_msgctl_args *)); int linux_msgget __P((struct proc *, struct linux_msgget_args *)); @@ -60,6 +125,7 @@ int linux_shmat __P((struct proc *, struct linux_shmat_args *)); int linux_shmctl __P((struct proc *, struct linux_shmctl_args *)); int linux_shmdt __P((struct proc *, struct linux_shmdt_args *)); int linux_shmget __P((struct proc *, struct linux_shmget_args *)); -#endif /*!__alpha__*/ + +#endif /* __i386__ */ #endif /* _LINUX_IPC_H_ */ diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c index e15b2a4..fda251b 100644 --- a/sys/compat/linux/linux_mib.c +++ b/sys/compat/linux/linux_mib.c @@ -69,7 +69,7 @@ SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 0, 0, linux_sysctl_osname, "A", "Linux kernel OS name"); -static char linux_osrelease[LINUX_MAX_UTSNAME] = "2.2.12"; +static char linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2"; static int linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 6c270fc..a717d81 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -40,6 +40,7 @@ #include <sys/mount.h> #include <sys/mutex.h> #include <sys/namei.h> +#include <sys/poll.h> #include <sys/proc.h> #include <sys/blist.h> #include <sys/reboot.h> @@ -85,87 +86,79 @@ (((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig) #endif -struct linux_rlimit { - unsigned long rlim_cur; - unsigned long rlim_max; -}; - #ifndef __alpha__ -static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = -{ RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, - RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, - RLIMIT_MEMLOCK, -1 +static unsigned int linux_to_bsd_resource[LINUX_RLIM_NLIMITS] = { + RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, + RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, + RLIMIT_MEMLOCK, -1 }; #endif /*!__alpha__*/ -struct linux_sysinfo { - long uptime; /* Seconds since boot */ - unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ - unsigned long totalram; /* Total usable main memory size */ - unsigned long freeram; /* Available memory size */ - unsigned long sharedram; /* Amount of shared memory */ - unsigned long bufferram; /* Memory used by buffers */ - unsigned long totalswap; /* Total swap space size */ - unsigned long freeswap; /* swap space still available */ - unsigned short procs; /* Number of current processes */ - char _f[22]; /* Pads structure to 64 bytes */ +struct l_sysinfo { + l_long uptime; /* Seconds since boot */ + l_ulong loads[3]; /* 1, 5, and 15 minute load averages */ + l_ulong totalram; /* Total usable main memory size */ + l_ulong freeram; /* Available memory size */ + l_ulong sharedram; /* Amount of shared memory */ + l_ulong bufferram; /* Memory used by buffers */ + l_ulong totalswap; /* Total swap space size */ + l_ulong freeswap; /* swap space still available */ + l_ushort procs; /* Number of current processes */ + char _f[22]; /* Pads structure to 64 bytes */ }; - #ifndef __alpha__ int linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args) { - struct linux_sysinfo sysinfo; - vm_object_t object; - int i; - struct timespec ts; - - /* Uptime is copied out of print_uptime() procedure in kern_shutdown.c */ - getnanouptime(&ts); - i = 0; - if (ts.tv_sec >= 86400) { - ts.tv_sec %= 86400; - i = 1; - } - if (i || ts.tv_sec >= 3600) { - ts.tv_sec %= 3600; - i = 1; - } - if (i || ts.tv_sec >= 60) { - ts.tv_sec %= 60; - i = 1; - } - sysinfo.uptime=ts.tv_sec; - - /* Use the information from the mib to get our load averages */ - for (i = 0; i < 3; i++) - sysinfo.loads[i] = averunnable.ldavg[i]; - - sysinfo.totalram = physmem * PAGE_SIZE; - sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE; - - sysinfo.sharedram = 0; - for (object = TAILQ_FIRST(&vm_object_list); object != NULL; - object = TAILQ_NEXT(object, object_list)) - if (object->shadow_count > 1) - sysinfo.sharedram += object->resident_page_count; - - sysinfo.sharedram *= PAGE_SIZE; - - sysinfo.bufferram = 0; - - if (swapblist == NULL) { - sysinfo.totalswap= 0; - sysinfo.freeswap = 0; - } else { - sysinfo.totalswap = swapblist->bl_blocks * 1024; - sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE; - } - - sysinfo.procs = 20; /* Hack */ - - return copyout((caddr_t)&sysinfo, (caddr_t)args->info, - sizeof(struct linux_sysinfo)); + struct l_sysinfo sysinfo; + vm_object_t object; + int i; + struct timespec ts; + + /* Uptime is copied out of print_uptime() in kern_shutdown.c */ + getnanouptime(&ts); + i = 0; + if (ts.tv_sec >= 86400) { + ts.tv_sec %= 86400; + i = 1; + } + if (i || ts.tv_sec >= 3600) { + ts.tv_sec %= 3600; + i = 1; + } + if (i || ts.tv_sec >= 60) { + ts.tv_sec %= 60; + i = 1; + } + sysinfo.uptime=ts.tv_sec; + + /* Use the information from the mib to get our load averages */ + for (i = 0; i < 3; i++) + sysinfo.loads[i] = averunnable.ldavg[i]; + + sysinfo.totalram = physmem * PAGE_SIZE; + sysinfo.freeram = sysinfo.totalram - cnt.v_wire_count * PAGE_SIZE; + + sysinfo.sharedram = 0; + for (object = TAILQ_FIRST(&vm_object_list); object != NULL; + object = TAILQ_NEXT(object, object_list)) + if (object->shadow_count > 1) + sysinfo.sharedram += object->resident_page_count; + + sysinfo.sharedram *= PAGE_SIZE; + sysinfo.bufferram = 0; + + if (swapblist == NULL) { + sysinfo.totalswap= 0; + sysinfo.freeswap = 0; + } else { + sysinfo.totalswap = swapblist->bl_blocks * 1024; + sysinfo.freeswap = swapblist->bl_root->u.bmu_avail * PAGE_SIZE; + } + + sysinfo.procs = 20; /* Hack */ + + return copyout(&sysinfo, (caddr_t)args->info, sizeof(sysinfo)); } #endif /*!__alpha__*/ @@ -173,475 +166,427 @@ linux_sysinfo(struct proc *p, struct linux_sysinfo_args *args) int linux_alarm(struct proc *p, struct linux_alarm_args *args) { - struct itimerval it, old_it; - struct timeval tv; - int s; + struct itimerval it, old_it; + struct timeval tv; + int s; #ifdef DEBUG if (ldebug(alarm)) printf(ARGS(alarm, "%u"), args->secs); #endif - if (args->secs > 100000000) - return EINVAL; - it.it_value.tv_sec = (long)args->secs; - it.it_value.tv_usec = 0; - it.it_interval.tv_sec = 0; - it.it_interval.tv_usec = 0; - s = splsoftclock(); - old_it = p->p_realtimer; - getmicrouptime(&tv); - if (timevalisset(&old_it.it_value)) - callout_stop(&p->p_itcallout); - if (it.it_value.tv_sec != 0) { - callout_reset(&p->p_itcallout, tvtohz(&it.it_value), realitexpire, p); - timevaladd(&it.it_value, &tv); - } - p->p_realtimer = it; - splx(s); - if (timevalcmp(&old_it.it_value, &tv, >)) { - timevalsub(&old_it.it_value, &tv); - if (old_it.it_value.tv_usec != 0) - old_it.it_value.tv_sec++; - p->p_retval[0] = old_it.it_value.tv_sec; - } - return 0; + + if (args->secs > 100000000) + return EINVAL; + + it.it_value.tv_sec = (long)args->secs; + it.it_value.tv_usec = 0; + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + s = splsoftclock(); + old_it = p->p_realtimer; + getmicrouptime(&tv); + if (timevalisset(&old_it.it_value)) + callout_stop(&p->p_itcallout); + if (it.it_value.tv_sec != 0) { + callout_reset(&p->p_itcallout, tvtohz(&it.it_value), + realitexpire, p); + timevaladd(&it.it_value, &tv); + } + p->p_realtimer = it; + splx(s); + if (timevalcmp(&old_it.it_value, &tv, >)) { + timevalsub(&old_it.it_value, &tv); + if (old_it.it_value.tv_usec != 0) + old_it.it_value.tv_sec++; + p->p_retval[0] = old_it.it_value.tv_sec; + } + return 0; } #endif /*!__alpha__*/ int linux_brk(struct proc *p, struct linux_brk_args *args) { -#if 0 - struct vmspace *vm = p->p_vmspace; - vm_offset_t new, old; - int error; - - if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) - return EINVAL; - if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) - > p->p_rlimit[RLIMIT_DATA].rlim_cur) - return ENOMEM; - - old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); - new = round_page((vm_offset_t)args->dsend); - p->p_retval[0] = old; - if ((new-old) > 0) { - if (swap_pager_full) - return ENOMEM; - error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) - return error; - vm->vm_dsize += btoc((new-old)); - p->p_retval[0] = (int)(vm->vm_daddr + ctob(vm->vm_dsize)); - } - return 0; -#else - struct vmspace *vm = p->p_vmspace; - vm_offset_t new, old; - struct obreak_args /* { - char * nsize; - } */ tmp; + struct vmspace *vm = p->p_vmspace; + vm_offset_t new, old; + struct obreak_args /* { + char * nsize; + } */ tmp; #ifdef DEBUG if (ldebug(brk)) printf(ARGS(brk, "%p"), (void *)args->dsend); #endif - old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); - new = (vm_offset_t)args->dsend; - tmp.nsize = (char *) new; - if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp)) - p->p_retval[0] = (long)new; - else - p->p_retval[0] = (long)old; - - return 0; -#endif + old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); + new = (vm_offset_t)args->dsend; + tmp.nsize = (char *) new; + if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp)) + p->p_retval[0] = (long)new; + else + p->p_retval[0] = (long)old; + + return 0; } int linux_uselib(struct proc *p, struct linux_uselib_args *args) { - struct nameidata ni; - struct vnode *vp; - struct exec *a_out; - struct vattr attr; - vm_offset_t vmaddr; - unsigned long file_offset; - vm_offset_t buffer; - unsigned long bss_size; - int error; - caddr_t sg; - int locked; - - sg = stackgap_init(); - CHECKALTEXIST(p, &sg, args->library); + struct nameidata ni; + struct vnode *vp; + struct exec *a_out; + struct vattr attr; + vm_offset_t vmaddr; + unsigned long file_offset; + vm_offset_t buffer; + unsigned long bss_size; + int error; + caddr_t sg; + int locked; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->library); #ifdef DEBUG if (ldebug(uselib)) printf(ARGS(uselib, "%s"), args->library); #endif - a_out = NULL; - locked = 0; - vp = NULL; - - NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, args->library, p); - error = namei(&ni); - if (error) - goto cleanup; - - vp = ni.ni_vp; - /* - * XXX This looks like a bogus check - a LOCKLEAF namei should not succeed - * without returning a vnode. - */ - if (vp == NULL) { - error = ENOEXEC; /* ?? */ - goto cleanup; - } - NDFREE(&ni, NDF_ONLY_PNBUF); - - /* - * From here on down, we have a locked vnode that must be unlocked. - */ - locked++; - - /* - * Writable? - */ - if (vp->v_writecount) { - error = ETXTBSY; - goto cleanup; - } - - /* - * Executable? - */ - error = VOP_GETATTR(vp, &attr, p->p_ucred, p); - if (error) - goto cleanup; - - if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || - ((attr.va_mode & 0111) == 0) || - (attr.va_type != VREG)) { - error = ENOEXEC; - goto cleanup; - } - - /* - * Sensible size? - */ - if (attr.va_size == 0) { - error = ENOEXEC; - goto cleanup; - } - - /* - * Can we access it? - */ - error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); - if (error) - goto cleanup; - - error = VOP_OPEN(vp, FREAD, p->p_ucred, p); - if (error) - goto cleanup; - - /* - * Lock no longer needed - */ - VOP_UNLOCK(vp, 0, p); - locked = 0; - - /* - * Pull in executable header into kernel_map - */ - error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, - VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); - if (error) - goto cleanup; - - /* - * Is it a Linux binary ? - */ - if (((a_out->a_magic >> 16) & 0xff) != 0x64) { - error = ENOEXEC; - goto cleanup; - } - - /* While we are here, we should REALLY do some more checks */ - - /* - * Set file/virtual offset based on a.out variant. - */ - switch ((int)(a_out->a_magic & 0xffff)) { - case 0413: /* ZMAGIC */ - file_offset = 1024; - break; - case 0314: /* QMAGIC */ - file_offset = 0; - break; - default: - error = ENOEXEC; - goto cleanup; - } - - bss_size = round_page(a_out->a_bss); - - /* - * Check various fields in header for validity/bounds. - */ - if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { - error = ENOEXEC; - goto cleanup; - } - - /* text + data can't exceed file size */ - if (a_out->a_data + a_out->a_text > attr.va_size) { - error = EFAULT; - goto cleanup; - } - - /* To protect p->p_rlimit in the if condition. */ - mtx_assert(&Giant, MA_OWNED); - - /* - * text/data/bss must not exceed limits - * XXX: this is not complete. it should check current usage PLUS - * the resources needed by this library. - */ - if (a_out->a_text > MAXTSIZ || - a_out->a_data + bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { - error = ENOMEM; - goto cleanup; - } - - /* - * prevent more writers - */ - vp->v_flag |= VTEXT; - - /* - * Check if file_offset page aligned,. - * Currently we cannot handle misalinged file offsets, - * and so we read in the entire image (what a waste). - */ - if (file_offset & PAGE_MASK) { -#ifdef DEBUG -printf("uselib: Non page aligned binary %lu\n", file_offset); -#endif + a_out = NULL; + locked = 0; + vp = NULL; + + NDINIT(&ni, LOOKUP, FOLLOW|LOCKLEAF, UIO_USERSPACE, args->library, p); + error = namei(&ni); + if (error) + goto cleanup; + + vp = ni.ni_vp; /* - * Map text+data read/write/execute + * XXX - This looks like a bogus check. A LOCKLEAF namei should not + * succeed without returning a vnode. */ + if (vp == NULL) { + error = ENOEXEC; /* ?? */ + goto cleanup; + } + NDFREE(&ni, NDF_ONLY_PNBUF); - /* a_entry is the load address and is page aligned */ - vmaddr = trunc_page(a_out->a_entry); + /* + * From here on down, we have a locked vnode that must be unlocked. + */ + locked++; - /* get anon user mapping, read+write+execute */ - error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, - a_out->a_text + a_out->a_data, FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) - goto cleanup; + /* Writable? */ + if (vp->v_writecount) { + error = ETXTBSY; + goto cleanup; + } - /* map file into kernel_map */ - error = vm_mmap(kernel_map, &buffer, - round_page(a_out->a_text + a_out->a_data + file_offset), - VM_PROT_READ, VM_PROT_READ, 0, - (caddr_t)vp, trunc_page(file_offset)); + /* Executable? */ + error = VOP_GETATTR(vp, &attr, p->p_ucred, p); if (error) - goto cleanup; + goto cleanup; - /* copy from kernel VM space to user space */ - error = copyout((caddr_t)(void *)(uintptr_t)(buffer + file_offset), - (caddr_t)vmaddr, a_out->a_text + a_out->a_data); + if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || + ((attr.va_mode & 0111) == 0) || (attr.va_type != VREG)) { + error = ENOEXEC; + goto cleanup; + } - /* release temporary kernel space */ - vm_map_remove(kernel_map, buffer, - buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); + /* Sensible size? */ + if (attr.va_size == 0) { + error = ENOEXEC; + goto cleanup; + } + /* Can we access it? */ + error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); if (error) - goto cleanup; - } - else { -#ifdef DEBUG -printf("uselib: Page aligned binary %lu\n", file_offset); -#endif + goto cleanup; + + error = VOP_OPEN(vp, FREAD, p->p_ucred, p); + if (error) + goto cleanup; + /* - * for QMAGIC, a_entry is 20 bytes beyond the load address - * to skip the executable header + * Lock no longer needed */ - vmaddr = trunc_page(a_out->a_entry); + VOP_UNLOCK(vp, 0, p); + locked = 0; + + /* Pull in executable header into kernel_map */ + error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, + VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); + if (error) + goto cleanup; + + /* Is it a Linux binary ? */ + if (((a_out->a_magic >> 16) & 0xff) != 0x64) { + error = ENOEXEC; + goto cleanup; + } /* - * Map it all into the process's space as a single copy-on-write - * "data" segment. + * While we are here, we should REALLY do some more checks */ - error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, - a_out->a_text + a_out->a_data, - VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, - (caddr_t)vp, file_offset); - if (error) - goto cleanup; - } -#ifdef DEBUG -printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0], ((long*)vmaddr)[1]); -#endif - if (bss_size != 0) { - /* - * Calculate BSS start address + + /* Set file/virtual offset based on a.out variant. */ + switch ((int)(a_out->a_magic & 0xffff)) { + case 0413: /* ZMAGIC */ + file_offset = 1024; + break; + case 0314: /* QMAGIC */ + file_offset = 0; + break; + default: + error = ENOEXEC; + goto cleanup; + } + + bss_size = round_page(a_out->a_bss); + + /* Check various fields in header for validity/bounds. */ + if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { + error = ENOEXEC; + goto cleanup; + } + + /* text + data can't exceed file size */ + if (a_out->a_data + a_out->a_text > attr.va_size) { + error = EFAULT; + goto cleanup; + } + + /* To protect p->p_rlimit in the if condition. */ + mtx_assert(&Giant, MA_OWNED); + + /* + * text/data/bss must not exceed limits + * XXX - this is not complete. it should check current usage PLUS + * the resources needed by this library. */ - vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; + if (a_out->a_text > MAXTSIZ || + a_out->a_data + bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { + error = ENOMEM; + goto cleanup; + } + + /* prevent more writers */ + vp->v_flag |= VTEXT; /* - * allocate some 'anon' space + * Check if file_offset page aligned. Currently we cannot handle + * misalinged file offsets, and so we read in the entire image + * (what a waste). */ - error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, - bss_size, FALSE, - VM_PROT_ALL, VM_PROT_ALL, 0); - if (error) - goto cleanup; - } + if (file_offset & PAGE_MASK) { +#ifdef DEBUG + printf("uselib: Non page aligned binary %lu\n", file_offset); +#endif + /* Map text+data read/write/execute */ + + /* a_entry is the load address and is page aligned */ + vmaddr = trunc_page(a_out->a_entry); + + /* get anon user mapping, read+write+execute */ + error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, + a_out->a_text + a_out->a_data, FALSE, VM_PROT_ALL, + VM_PROT_ALL, 0); + if (error) + goto cleanup; + + /* map file into kernel_map */ + error = vm_mmap(kernel_map, &buffer, + round_page(a_out->a_text + a_out->a_data + file_offset), + VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, + trunc_page(file_offset)); + if (error) + goto cleanup; + + /* copy from kernel VM space to user space */ + error = copyout((caddr_t)(uintptr_t)(buffer + file_offset), + (caddr_t)vmaddr, a_out->a_text + a_out->a_data); + + /* release temporary kernel space */ + vm_map_remove(kernel_map, buffer, buffer + + round_page(a_out->a_text + a_out->a_data + file_offset)); + + if (error) + goto cleanup; + } else { +#ifdef DEBUG + printf("uselib: Page aligned binary %lu\n", file_offset); +#endif + /* + * for QMAGIC, a_entry is 20 bytes beyond the load address + * to skip the executable header + */ + vmaddr = trunc_page(a_out->a_entry); + + /* + * Map it all into the process's space as a single + * copy-on-write "data" segment. + */ + error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, + a_out->a_text + a_out->a_data, VM_PROT_ALL, VM_PROT_ALL, + MAP_PRIVATE | MAP_FIXED, (caddr_t)vp, file_offset); + if (error) + goto cleanup; + } +#ifdef DEBUG + printf("mem=%08lx = %08lx %08lx\n", (long)vmaddr, ((long*)vmaddr)[0], + ((long*)vmaddr)[1]); +#endif + if (bss_size != 0) { + /* Calculate BSS start address */ + vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + + a_out->a_data; + + /* allocate some 'anon' space */ + error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, + bss_size, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0); + if (error) + goto cleanup; + } cleanup: - /* - * Unlock vnode if needed - */ - if (locked) - VOP_UNLOCK(vp, 0, p); + /* Unlock vnode if needed */ + if (locked) + VOP_UNLOCK(vp, 0, p); - /* - * Release the kernel mapping. - */ - if (a_out) - vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); + /* Release the kernel mapping. */ + if (a_out) + vm_map_remove(kernel_map, (vm_offset_t)a_out, + (vm_offset_t)a_out + PAGE_SIZE); - return error; + return error; } int -linux_newselect(struct proc *p, struct linux_newselect_args *args) +linux_select(struct proc *p, struct linux_select_args *args) { - struct select_args bsa; - struct timeval tv0, tv1, utv, *tvp; - caddr_t sg; - int error; + struct select_args bsa; + struct timeval tv0, tv1, utv, *tvp; + caddr_t sg; + int error; #ifdef DEBUG - if (ldebug(newselect)) - printf(ARGS(newselect, "%d, %p, %p, %p, %p"), - args->nfds, (void *)args->readfds, - (void *)args->writefds, (void *)args->exceptfds, - (void *)args->timeout); + if (ldebug(select)) + printf(ARGS(select, "%d, %p, %p, %p, %p"), args->nfds, + (void *)args->readfds, (void *)args->writefds, + (void *)args->exceptfds, (void *)args->timeout); #endif - error = 0; - bsa.nd = args->nfds; - bsa.in = args->readfds; - bsa.ou = args->writefds; - bsa.ex = args->exceptfds; - bsa.tv = args->timeout; - - /* - * 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; + + error = 0; + bsa.nd = args->nfds; + bsa.in = args->readfds; + bsa.ou = args->writefds; + bsa.ex = args->exceptfds; + bsa.tv = (struct timeval *)args->timeout; + + /* + * Store current time for computation of the amount of + * time left. + */ + if (args->timeout) { + if ((error = copyin((caddr_t)args->timeout, &utv, + sizeof(utv)))) + goto select_out; #ifdef DEBUG - if (ldebug(newselect)) - printf(LMSG("incoming timeout (%ld/%ld)"), - utv.tv_sec, utv.tv_usec); + if (ldebug(select)) + printf(LMSG("incoming timeout (%ld/%ld)"), + 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) - timevalclear(&utv); - if ((error = copyout(&utv, tvp, sizeof(utv)))) - goto select_out; - bsa.tv = tvp; + + 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) + timevalclear(&utv); + if ((error = copyout(&utv, tvp, sizeof(utv)))) + goto select_out; + bsa.tv = tvp; + } + microtime(&tv0); } - microtime(&tv0); - } - error = select(p, &bsa); + error = select(p, &bsa); #ifdef DEBUG - if (ldebug(newselect)) + if (ldebug(select)) printf(LMSG("real select returns %d"), 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 (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 (p->p_retval[0]) { - /* - * 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) - timevalclear(&utv); - } else - timevalclear(&utv); + if (args->timeout) { + if (p->p_retval[0]) { + /* + * 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) + timevalclear(&utv); + } else + timevalclear(&utv); #ifdef DEBUG - if (ldebug(newselect)) - printf(LMSG("outgoing timeout (%ld/%ld)"), - utv.tv_sec, utv.tv_usec); + if (ldebug(select)) + printf(LMSG("outgoing timeout (%ld/%ld)"), + utv.tv_sec, utv.tv_usec); #endif - if ((error = copyout(&utv, args->timeout, sizeof(utv)))) - goto select_out; - } + if ((error = copyout(&utv, (caddr_t)args->timeout, + sizeof(utv)))) + goto select_out; + } select_out: #ifdef DEBUG - if (ldebug(newselect)) - printf(LMSG("newselect_out -> %d"), error); + if (ldebug(select)) + printf(LMSG("select_out -> %d"), error); #endif - return error; + return error; } int linux_getpgid(struct proc *p, struct linux_getpgid_args *args) { - struct proc *curp; + struct proc *curp; #ifdef DEBUG if (ldebug(getpgid)) printf(ARGS(getpgid, "%d"), args->pid); #endif - if (args->pid != p->p_pid) { - if (!(curp = pfind(args->pid))) - return ESRCH; - p->p_retval[0] = curp->p_pgid; - PROC_UNLOCK(curp); - } - else - p->p_retval[0] = p->p_pgid; - return 0; + + if (args->pid != p->p_pid) { + if (!(curp = pfind(args->pid))) + return ESRCH; + p->p_retval[0] = curp->p_pgid; + PROC_UNLOCK(curp); + } else + p->p_retval[0] = p->p_pgid; + + return 0; } int @@ -670,7 +615,7 @@ linux_mremap(struct proc *p, struct linux_mremap_args *args) } if (args->new_len < args->old_len) { - bsd_args.addr = args->addr + args->new_len; + bsd_args.addr = (caddr_t)(args->addr + args->new_len); bsd_args.len = args->old_len - args->new_len; error = munmap(p, &bsd_args); } @@ -684,7 +629,7 @@ linux_msync(struct proc *p, struct linux_msync_args *args) { struct msync_args bsd_args; - bsd_args.addr = args->addr; + bsd_args.addr = (caddr_t)args->addr; bsd_args.len = args->len; bsd_args.flags = 0; /* XXX ignore */ @@ -695,28 +640,29 @@ linux_msync(struct proc *p, struct linux_msync_args *args) int linux_time(struct proc *p, struct linux_time_args *args) { - struct timeval tv; - linux_time_t tm; - int error; + struct timeval tv; + l_time_t tm; + int error; #ifdef DEBUG if (ldebug(time)) printf(ARGS(time, "*")); #endif - microtime(&tv); - tm = tv.tv_sec; - if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t)))) - return error; - p->p_retval[0] = tm; - return 0; + + microtime(&tv); + tm = tv.tv_sec; + if (args->tm && (error = copyout(&tm, (caddr_t)args->tm, sizeof(tm)))) + return error; + p->p_retval[0] = tm; + return 0; } #endif /*!__alpha__*/ -struct linux_times_argv { - long tms_utime; - long tms_stime; - long tms_cutime; - long tms_cstime; +struct l_times_argv { + l_long tms_utime; + l_long tms_stime; + l_long tms_cutime; + l_long tms_cstime; }; #ifdef __alpha__ @@ -730,38 +676,38 @@ struct linux_times_argv { int linux_times(struct proc *p, struct linux_times_args *args) { - struct timeval tv; - struct linux_times_argv tms; - struct rusage ru; - int error; + struct timeval tv; + struct l_times_argv tms; + struct rusage ru; + int error; #ifdef DEBUG if (ldebug(times)) printf(ARGS(times, "*")); #endif - mtx_lock_spin(&sched_lock); - calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); - mtx_unlock_spin(&sched_lock); - tms.tms_utime = CONVTCK(ru.ru_utime); - tms.tms_stime = CONVTCK(ru.ru_stime); + mtx_lock_spin(&sched_lock); + calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); + mtx_unlock_spin(&sched_lock); - tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); - tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); + tms.tms_utime = CONVTCK(ru.ru_utime); + tms.tms_stime = CONVTCK(ru.ru_stime); - if ((error = copyout((caddr_t)&tms, (caddr_t)args->buf, - sizeof(struct linux_times_argv)))) - return error; + tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); + tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); + + if ((error = copyout(&tms, (caddr_t)args->buf, sizeof(tms)))) + return error; - microuptime(&tv); - p->p_retval[0] = (int)CONVTCK(tv); - return 0; + microuptime(&tv); + p->p_retval[0] = (int)CONVTCK(tv); + return 0; } int linux_newuname(struct proc *p, struct linux_newuname_args *args) { - struct linux_new_utsname utsname; + struct l_new_utsname utsname; char *osrelease, *osname; #ifdef DEBUG @@ -772,7 +718,7 @@ linux_newuname(struct proc *p, struct linux_newuname_args *args) osname = linux_get_osname(p); osrelease = linux_get_osrelease(p); - bzero(&utsname, sizeof(struct linux_new_utsname)); + bzero(&utsname, sizeof(utsname)); strncpy(utsname.sysname, osname, LINUX_MAX_UTSNAME-1); strncpy(utsname.nodename, hostname, LINUX_MAX_UTSNAME-1); strncpy(utsname.release, osrelease, LINUX_MAX_UTSNAME-1); @@ -780,54 +726,56 @@ linux_newuname(struct proc *p, struct linux_newuname_args *args) strncpy(utsname.machine, machine, LINUX_MAX_UTSNAME-1); strncpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME-1); - return (copyout((caddr_t)&utsname, (caddr_t)args->buf, - sizeof(struct linux_new_utsname))); + return (copyout(&utsname, (caddr_t)args->buf, sizeof(utsname))); } -struct linux_utimbuf { - linux_time_t l_actime; - linux_time_t l_modtime; +#if defined(__i386__) +struct l_utimbuf { + l_time_t l_actime; + l_time_t l_modtime; }; int linux_utime(struct proc *p, struct linux_utime_args *args) { - struct utimes_args /* { - char *path; - struct timeval *tptr; - } */ bsdutimes; - struct timeval tv[2], *tvp; - struct linux_utimbuf lut; - int error; - caddr_t sg; - - sg = stackgap_init(); - CHECKALTEXIST(p, &sg, args->fname); + struct utimes_args /* { + char *path; + struct timeval *tptr; + } */ bsdutimes; + struct timeval tv[2], *tvp; + struct l_utimbuf lut; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->fname); #ifdef DEBUG if (ldebug(utime)) printf(ARGS(utime, "%s, *"), args->fname); #endif - if (args->times) { - if ((error = copyin(args->times, &lut, sizeof lut))) - return error; - tv[0].tv_sec = lut.l_actime; - tv[0].tv_usec = 0; - tv[1].tv_sec = lut.l_modtime; - tv[1].tv_usec = 0; - /* so that utimes can copyin */ - tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); - if (tvp == NULL) - return (ENAMETOOLONG); - if ((error = copyout(tv, tvp, sizeof(tv)))) - return error; - bsdutimes.tptr = tvp; - } else - bsdutimes.tptr = NULL; - - bsdutimes.path = args->fname; - return utimes(p, &bsdutimes); + + if (args->times) { + if ((error = copyin((caddr_t)args->times, &lut, sizeof lut))) + return error; + tv[0].tv_sec = lut.l_actime; + tv[0].tv_usec = 0; + tv[1].tv_sec = lut.l_modtime; + tv[1].tv_usec = 0; + /* so that utimes can copyin */ + tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); + if (tvp == NULL) + return (ENAMETOOLONG); + if ((error = copyout(tv, tvp, sizeof(tv)))) + return error; + bsdutimes.tptr = tvp; + } else + bsdutimes.tptr = NULL; + + bsdutimes.path = args->fname; + return utimes(p, &bsdutimes); } +#endif /* __i386__ */ #define __WCLONE 0x80000000 @@ -835,42 +783,45 @@ linux_utime(struct proc *p, struct linux_utime_args *args) int linux_waitpid(struct proc *p, struct linux_waitpid_args *args) { - struct wait_args /* { - int pid; - int *status; - int options; - struct rusage *rusage; - } */ tmp; - int error, tmpstat; + struct wait_args /* { + int pid; + int *status; + int options; + struct rusage *rusage; + } */ tmp; + int error, tmpstat; #ifdef DEBUG if (ldebug(waitpid)) printf(ARGS(waitpid, "%d, %p, %d"), args->pid, (void *)args->status, args->options); #endif - tmp.pid = args->pid; - tmp.status = args->status; - tmp.options = (args->options & (WNOHANG | WUNTRACED)); - /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ - if (args->options & __WCLONE) - tmp.options |= WLINUXCLONE; - tmp.rusage = NULL; - - if ((error = wait4(p, &tmp)) != 0) - return error; - if (args->status) { - if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0) - return error; - tmpstat &= 0xffff; - 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 + tmp.pid = args->pid; + tmp.status = args->status; + tmp.options = (args->options & (WNOHANG | WUNTRACED)); + /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ + if (args->options & __WCLONE) + tmp.options |= WLINUXCLONE; + tmp.rusage = NULL; + + if ((error = wait4(p, &tmp)) != 0) + return error; + + if (args->status) { + if ((error = copyin((caddr_t)args->status, &tmpstat, + sizeof(int))) != 0) + return error; + tmpstat &= 0xffff; + 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, (caddr_t)args->status, sizeof(int)); + } + return 0; } #endif /*!__alpha__*/ @@ -878,13 +829,13 @@ linux_waitpid(struct proc *p, struct linux_waitpid_args *args) int linux_wait4(struct proc *p, struct linux_wait4_args *args) { - struct wait_args /* { - int pid; - int *status; - int options; - struct rusage *rusage; - } */ tmp; - int error, tmpstat; + struct wait_args /* { + int pid; + int *status; + int options; + struct rusage *rusage; + } */ tmp; + int error, tmpstat; #ifdef DEBUG if (ldebug(wait4)) @@ -892,31 +843,34 @@ linux_wait4(struct proc *p, struct linux_wait4_args *args) args->pid, (void *)args->status, args->options, (void *)args->rusage); #endif - tmp.pid = args->pid; - tmp.status = args->status; - tmp.options = (args->options & (WNOHANG | WUNTRACED)); - /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ - if (args->options & __WCLONE) - tmp.options |= WLINUXCLONE; - tmp.rusage = args->rusage; - - if ((error = wait4(p, &tmp)) != 0) - return error; - SIGDELSET(p->p_siglist, SIGCHLD); - - if (args->status) { - if ((error = copyin(args->status, &tmpstat, sizeof(int))) != 0) - return error; - tmpstat &= 0xffff; - 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 + tmp.pid = args->pid; + tmp.status = args->status; + tmp.options = (args->options & (WNOHANG | WUNTRACED)); + /* WLINUXCLONE should be equal to __WCLONE, but we make sure */ + if (args->options & __WCLONE) + tmp.options |= WLINUXCLONE; + tmp.rusage = (struct rusage *)args->rusage; + + if ((error = wait4(p, &tmp)) != 0) + return error; + + SIGDELSET(p->p_siglist, SIGCHLD); + + if (args->status) { + if ((error = copyin((caddr_t)args->status, &tmpstat, + sizeof(int))) != 0) + return error; + tmpstat &= 0xffff; + 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, (caddr_t)args->status, sizeof(int)); + } + return 0; } @@ -985,11 +939,10 @@ linux_setitimer(struct proc *p, struct linux_setitimer_args *args) (void *)args->itv, (void *)args->oitv); #endif bsa.which = args->which; - bsa.itv = args->itv; - bsa.oitv = args->oitv; + bsa.itv = (struct itimerval *)args->itv; + bsa.oitv = (struct itimerval *)args->oitv; if (args->itv) { - if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo, - sizeof(foo)))) + if ((error = copyin((caddr_t)args->itv, &foo, sizeof(foo)))) return error; #ifdef DEBUG if (ldebug(setitimer)) { @@ -1012,7 +965,7 @@ linux_getitimer(struct proc *p, struct linux_getitimer_args *args) printf(ARGS(getitimer, "%p"), (void *)args->itv); #endif bsa.which = args->which; - bsa.itv = args->itv; + bsa.itv = (struct itimerval *)args->itv; return getitimer(p, &bsa); } @@ -1030,16 +983,14 @@ linux_nice(struct proc *p, struct linux_nice_args *args) #endif /*!__alpha__*/ int -linux_setgroups(p, uap) - struct proc *p; - struct linux_setgroups_args *uap; +linux_setgroups(struct proc *p, struct linux_setgroups_args *args) { struct ucred *newcred, *oldcred; - linux_gid_t linux_gidset[NGROUPS]; + l_gid_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int ngrp, error; - ngrp = uap->gidsetsize; + ngrp = args->gidsetsize; oldcred = p->p_ucred; /* @@ -1056,8 +1007,8 @@ linux_setgroups(p, uap) newcred = crdup(oldcred); if (ngrp > 0) { - error = copyin((caddr_t)uap->gidset, (caddr_t)linux_gidset, - ngrp * sizeof(linux_gid_t)); + error = copyin((caddr_t)args->grouplist, linux_gidset, + ngrp * sizeof(l_gid_t)); if (error) return (error); @@ -1080,12 +1031,10 @@ linux_setgroups(p, uap) } int -linux_getgroups(p, uap) - struct proc *p; - struct linux_getgroups_args *uap; +linux_getgroups(struct proc *p, struct linux_getgroups_args *args) { struct ucred *cred; - linux_gid_t linux_gidset[NGROUPS]; + l_gid_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; @@ -1099,7 +1048,7 @@ linux_getgroups(p, uap) * to prevent that. */ - if ((ngrp = uap->gidsetsize) == 0) { + if ((ngrp = args->gidsetsize) == 0) { p->p_retval[0] = bsd_gidsetsz; return (0); } @@ -1113,8 +1062,8 @@ linux_getgroups(p, uap) ngrp++; } - if ((error = copyout((caddr_t)linux_gidset, (caddr_t)uap->gidset, - ngrp * sizeof(linux_gid_t)))) + if ((error = copyout(linux_gidset, (caddr_t)args->grouplist, + ngrp * sizeof(l_gid_t)))) return (error); p->p_retval[0] = ngrp; @@ -1123,29 +1072,27 @@ linux_getgroups(p, uap) #ifndef __alpha__ int -linux_setrlimit(p, uap) - struct proc *p; - struct linux_setrlimit_args *uap; +linux_setrlimit(struct proc *p, struct linux_setrlimit_args *args) { struct __setrlimit_args bsd; - struct linux_rlimit rlim; + struct l_rlimit rlim; int error; caddr_t sg = stackgap_init(); #ifdef DEBUG if (ldebug(setrlimit)) printf(ARGS(setrlimit, "%d, %p"), - uap->resource, (void *)uap->rlim); + args->resource, (void *)args->rlim); #endif - if (uap->resource >= LINUX_RLIM_NLIMITS) + if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); - bsd.which = linux_to_bsd_resource[uap->resource]; + bsd.which = linux_to_bsd_resource[args->resource]; if (bsd.which == -1) return (EINVAL); - error = copyin(uap->rlim, &rlim, sizeof(rlim)); + error = copyin((caddr_t)args->rlim, &rlim, sizeof(rlim)); if (error) return (error); @@ -1156,25 +1103,23 @@ linux_setrlimit(p, uap) } int -linux_getrlimit(p, uap) - struct proc *p; - struct linux_getrlimit_args *uap; +linux_old_getrlimit(struct proc *p, struct linux_old_getrlimit_args *args) { struct __getrlimit_args bsd; - struct linux_rlimit rlim; + struct l_rlimit rlim; int error; caddr_t sg = stackgap_init(); #ifdef DEBUG - if (ldebug(getrlimit)) - printf(ARGS(getrlimit, "%d, %p"), - uap->resource, (void *)uap->rlim); + if (ldebug(old_getrlimit)) + printf(ARGS(old_getrlimit, "%d, %p"), + args->resource, (void *)args->rlim); #endif - if (uap->resource >= LINUX_RLIM_NLIMITS) + if (args->resource >= LINUX_RLIM_NLIMITS) return (EINVAL); - bsd.which = linux_to_bsd_resource[uap->resource]; + bsd.which = linux_to_bsd_resource[args->resource]; if (bsd.which == -1) return (EINVAL); @@ -1189,24 +1134,54 @@ linux_getrlimit(p, uap) rlim.rlim_max = (unsigned long)bsd.rlp->rlim_max; if (rlim.rlim_max == ULONG_MAX) rlim.rlim_max = LONG_MAX; - return (copyout(&rlim, uap->rlim, sizeof(rlim))); + return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); +} + +int +linux_getrlimit(struct proc *p, struct linux_getrlimit_args *args) +{ + struct __getrlimit_args bsd; + struct l_rlimit rlim; + int error; + caddr_t sg = stackgap_init(); + +#ifdef DEBUG + if (ldebug(getrlimit)) + printf(ARGS(getrlimit, "%d, %p"), + args->resource, (void *)args->rlim); +#endif + + if (args->resource >= LINUX_RLIM_NLIMITS) + return (EINVAL); + + bsd.which = linux_to_bsd_resource[args->resource]; + if (bsd.which == -1) + return (EINVAL); + + bsd.rlp = stackgap_alloc(&sg, sizeof(struct rlimit)); + error = getrlimit(p, &bsd); + if (error) + return (error); + + rlim.rlim_cur = (l_ulong)bsd.rlp->rlim_cur; + rlim.rlim_max = (l_ulong)bsd.rlp->rlim_max; + return (copyout(&rlim, (caddr_t)args->rlim, sizeof(rlim))); } #endif /*!__alpha__*/ int -linux_sched_setscheduler(p, uap) - struct proc *p; - struct linux_sched_setscheduler_args *uap; +linux_sched_setscheduler(struct proc *p, + struct linux_sched_setscheduler_args *args) { struct sched_setscheduler_args bsd; #ifdef DEBUG if (ldebug(sched_setscheduler)) printf(ARGS(sched_setscheduler, "%d, %d, %p"), - uap->pid, uap->policy, (const void *)uap->param); + args->pid, args->policy, (const void *)args->param); #endif - switch (uap->policy) { + switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; @@ -1220,25 +1195,24 @@ linux_sched_setscheduler(p, uap) return EINVAL; } - bsd.pid = uap->pid; - bsd.param = uap->param; + bsd.pid = args->pid; + bsd.param = (struct sched_param *)args->param; return sched_setscheduler(p, &bsd); } int -linux_sched_getscheduler(p, uap) - struct proc *p; - struct linux_sched_getscheduler_args *uap; +linux_sched_getscheduler(struct proc *p, + struct linux_sched_getscheduler_args *args) { struct sched_getscheduler_args bsd; int error; #ifdef DEBUG if (ldebug(sched_getscheduler)) - printf(ARGS(sched_getscheduler, "%d"), uap->pid); + printf(ARGS(sched_getscheduler, "%d"), args->pid); #endif - bsd.pid = uap->pid; + bsd.pid = args->pid; error = sched_getscheduler(p, &bsd); switch (p->p_retval[0]) { @@ -1257,18 +1231,17 @@ linux_sched_getscheduler(p, uap) } int -linux_sched_get_priority_max(p, uap) - struct proc *p; - struct linux_sched_get_priority_max_args *uap; +linux_sched_get_priority_max(struct proc *p, + struct linux_sched_get_priority_max_args *args) { struct sched_get_priority_max_args bsd; #ifdef DEBUG if (ldebug(sched_get_priority_max)) - printf(ARGS(sched_get_priority_max, "%d"), uap->policy); + printf(ARGS(sched_get_priority_max, "%d"), args->policy); #endif - switch (uap->policy) { + switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; @@ -1285,18 +1258,17 @@ linux_sched_get_priority_max(p, uap) } int -linux_sched_get_priority_min(p, uap) - struct proc *p; - struct linux_sched_get_priority_min_args *uap; +linux_sched_get_priority_min(struct proc *p, + struct linux_sched_get_priority_min_args *args) { struct sched_get_priority_min_args bsd; #ifdef DEBUG if (ldebug(sched_get_priority_min)) - printf(ARGS(sched_get_priority_min, "%d"), uap->policy); + printf(ARGS(sched_get_priority_min, "%d"), args->policy); #endif - switch (uap->policy) { + switch (args->policy) { case LINUX_SCHED_OTHER: bsd.policy = SCHED_OTHER; break; @@ -1323,10 +1295,43 @@ linux_reboot(struct proc *p, struct linux_reboot_args *args) #ifdef DEBUG if (ldebug(reboot)) - printf(ARGS(reboot, "0x%x"), args->opt); + printf(ARGS(reboot, "0x%x"), args->cmd); #endif - if (args->opt == REBOOT_CAD_ON || args->opt == REBOOT_CAD_OFF) + if (args->cmd == REBOOT_CAD_ON || args->cmd == REBOOT_CAD_OFF) return (0); - bsd_args.opt = args->opt == REBOOT_HALT ? RB_HALT : 0; + bsd_args.opt = (args->cmd == REBOOT_HALT) ? RB_HALT : 0; return (reboot(p, &bsd_args)); } + +/* + * The FreeBSD native getpid(2), getgid(2) and getuid(2) also modify + * p->p_retval[1] when COMPAT_43 or COMPAT_SUNOS is defined. This + * globbers registers that are assumed to be preserved. The following + * lightweight syscalls fixes this. See also linux_getgid16() and + * linux_getuid16() in linux_uid16.c. + * + * linux_getpid() - MP SAFE + * linux_getgid() - MP SAFE + * linux_getuid() - MP SAFE + */ + +int +linux_getpid(struct proc *p, struct linux_getpid_args *args) +{ + p->p_retval[0] = p->p_pid; + return (0); +} + +int +linux_getgid(struct proc *p, struct linux_getgid_args *args) +{ + p->p_retval[0] = p->p_ucred->cr_rgid; + return (0); +} + +int +linux_getuid(struct proc *p, struct linux_getuid_args *args) +{ + p->p_retval[0] = p->p_ucred->cr_ruid; + return (0); +} diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c index 8a2f8b3..24a540f 100644 --- a/sys/compat/linux/linux_signal.c +++ b/sys/compat/linux/linux_signal.c @@ -42,7 +42,7 @@ #include <compat/linux/linux_util.h> void -linux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss) +linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss) { int b, l; @@ -63,7 +63,7 @@ linux_to_bsd_sigset(linux_sigset_t *lss, sigset_t *bss) } void -bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) +bsd_to_linux_sigset(sigset_t *bss, l_sigset_t *lss) { int b, l; @@ -84,7 +84,7 @@ bsd_to_linux_sigset(sigset_t *bss, linux_sigset_t *lss) } static void -linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) +linux_to_bsd_sigaction(l_sigaction_t *lsa, struct sigaction *bsa) { linux_to_bsd_sigset(&lsa->lsa_mask, &bsa->sa_mask); @@ -107,7 +107,7 @@ linux_to_bsd_sigaction(linux_sigaction_t *lsa, struct sigaction *bsa) } static void -bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) +bsd_to_linux_sigaction(struct sigaction *bsa, l_sigaction_t *lsa) { bsd_to_linux_sigset(&bsa->sa_mask, &lsa->lsa_mask); @@ -131,8 +131,8 @@ bsd_to_linux_sigaction(struct sigaction *bsa, linux_sigaction_t *lsa) } int -linux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa, - linux_sigaction_t *linux_osa) +linux_do_sigaction(struct proc *p, int linux_sig, l_sigaction_t *linux_nsa, + l_sigaction_t *linux_osa) { struct sigaction *nsa, *osa; struct sigaction_args sa_args; @@ -178,7 +178,7 @@ linux_do_sigaction(struct proc *p, int linux_sig, linux_sigaction_t *linux_nsa, int linux_signal(struct proc *p, struct linux_signal_args *args) { - linux_sigaction_t nsa, osa; + l_sigaction_t nsa, osa; int error; #ifdef DEBUG @@ -201,7 +201,7 @@ linux_signal(struct proc *p, struct linux_signal_args *args) int linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) { - linux_sigaction_t nsa, osa; + l_sigaction_t nsa, osa; int error; #ifdef DEBUG @@ -211,11 +211,11 @@ linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) (void *)args->oact, (long)args->sigsetsize); #endif - if (args->sigsetsize != sizeof(linux_sigset_t)) + if (args->sigsetsize != sizeof(l_sigset_t)) return (EINVAL); if (args->act != NULL) { - error = copyin(args->act, &nsa, sizeof(linux_sigaction_t)); + error = copyin(args->act, &nsa, sizeof(l_sigaction_t)); if (error) return (error); } @@ -225,15 +225,15 @@ linux_rt_sigaction(struct proc *p, struct linux_rt_sigaction_args *args) args->oact ? &osa : NULL); if (args->oact != NULL && !error) { - error = copyout(&osa, args->oact, sizeof(linux_sigaction_t)); + error = copyout(&osa, args->oact, sizeof(l_sigaction_t)); } return (error); } static int -linux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, - linux_sigset_t *old) +linux_do_sigprocmask(struct proc *p, int how, l_sigset_t *new, + l_sigset_t *old) { int error; sigset_t mask; @@ -274,8 +274,8 @@ linux_do_sigprocmask(struct proc *p, int how, linux_sigset_t *new, int linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) { - linux_osigset_t mask; - linux_sigset_t set, oset; + l_osigset_t mask; + l_sigset_t set, oset; int error; #ifdef DEBUG @@ -284,7 +284,7 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) #endif if (args->mask != NULL) { - error = copyin(args->mask, &mask, sizeof(linux_osigset_t)); + error = copyin(args->mask, &mask, sizeof(l_osigset_t)); if (error) return (error); LINUX_SIGEMPTYSET(set); @@ -297,7 +297,7 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) if (args->omask != NULL && !error) { mask = oset.__bits[0]; - error = copyout(&mask, args->omask, sizeof(linux_osigset_t)); + error = copyout(&mask, args->omask, sizeof(l_osigset_t)); } return (error); @@ -307,7 +307,7 @@ linux_sigprocmask(struct proc *p, struct linux_sigprocmask_args *args) int linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) { - linux_sigset_t set, oset; + l_sigset_t set, oset; int error; #ifdef DEBUG @@ -317,11 +317,11 @@ linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) (void *)args->omask, (long)args->sigsetsize); #endif - if (args->sigsetsize != sizeof(linux_sigset_t)) + if (args->sigsetsize != sizeof(l_sigset_t)) return EINVAL; if (args->mask != NULL) { - error = copyin(args->mask, &set, sizeof(linux_sigset_t)); + error = copyin(args->mask, &set, sizeof(l_sigset_t)); if (error) return (error); } @@ -331,7 +331,7 @@ linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) args->omask ? &oset : NULL); if (args->omask != NULL && !error) { - error = copyout(&oset, args->omask, sizeof(linux_sigset_t)); + error = copyout(&oset, args->omask, sizeof(l_sigset_t)); } return (error); @@ -339,13 +339,13 @@ linux_rt_sigprocmask(struct proc *p, struct linux_rt_sigprocmask_args *args) #ifndef __alpha__ int -linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) +linux_sgetmask(struct proc *p, struct linux_sgetmask_args *args) { - linux_sigset_t mask; + l_sigset_t mask; #ifdef DEBUG - if (ldebug(siggetmask)) - printf(ARGS(siggetmask, "")); + if (ldebug(sgetmask)) + printf(ARGS(sgetmask, "")); #endif PROC_LOCK(p); @@ -356,14 +356,14 @@ linux_siggetmask(struct proc *p, struct linux_siggetmask_args *args) } int -linux_sigsetmask(struct proc *p, struct linux_sigsetmask_args *args) +linux_ssetmask(struct proc *p, struct linux_ssetmask_args *args) { - linux_sigset_t lset; + l_sigset_t lset; sigset_t bset; #ifdef DEBUG - if (ldebug(sigsetmask)) - printf(ARGS(sigsetmask, "%08lx"), (unsigned long)args->mask); + if (ldebug(ssetmask)) + printf(ARGS(ssetmask, "%08lx"), (unsigned long)args->mask); #endif PROC_LOCK(p); @@ -382,8 +382,8 @@ int linux_sigpending(struct proc *p, struct linux_sigpending_args *args) { sigset_t bset; - linux_sigset_t lset; - linux_osigset_t mask; + l_sigset_t lset; + l_osigset_t mask; #ifdef DEBUG if (ldebug(sigpending)) diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h index 2330b28..e9dcec0 100644 --- a/sys/compat/linux/linux_signal.h +++ b/sys/compat/linux/linux_signal.h @@ -31,9 +31,9 @@ #ifndef _LINUX_SIGNAL_H_ #define _LINUX_SIGNAL_H_ -void linux_to_bsd_sigset __P((linux_sigset_t *, sigset_t *)); -void bsd_to_linux_sigset __P((sigset_t *, linux_sigset_t *)); -int linux_do_sigaction __P((struct proc *, int, linux_sigaction_t *, - linux_sigaction_t *)); +void linux_to_bsd_sigset __P((l_sigset_t *, sigset_t *)); +void bsd_to_linux_sigset __P((sigset_t *, l_sigset_t *)); +int linux_do_sigaction __P((struct proc *, int, l_sigaction_t *, + l_sigaction_t *)); #endif /* _LINUX_SIGNAL_H_ */ diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index e47c725..ac73dde 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -423,7 +423,7 @@ linux_connect(struct proc *p, struct linux_connect_args *args) error = EISCONN; if (fp->f_flag & FNONBLOCK) { so = (struct socket *)fp->f_data; - if ((u_int)so->so_emuldata == 0) + if (so->so_emuldata == 0) error = so->so_error; so->so_emuldata = (void *)1; } @@ -870,38 +870,39 @@ linux_getsockopt(struct proc *p, struct linux_getsockopt_args *args) int linux_socketcall(struct proc *p, struct linux_socketcall_args *args) { + void *arg = (void *)args->args; switch (args->what) { case LINUX_SOCKET: - return (linux_socket(p, args->args)); + return (linux_socket(p, arg)); case LINUX_BIND: - return (linux_bind(p, args->args)); + return (linux_bind(p, arg)); case LINUX_CONNECT: - return (linux_connect(p, args->args)); + return (linux_connect(p, arg)); case LINUX_LISTEN: - return (linux_listen(p, args->args)); + return (linux_listen(p, arg)); case LINUX_ACCEPT: - return (linux_accept(p, args->args)); + return (linux_accept(p, arg)); case LINUX_GETSOCKNAME: - return (linux_getsockname(p, args->args)); + return (linux_getsockname(p, arg)); case LINUX_GETPEERNAME: - return (linux_getpeername(p, args->args)); + return (linux_getpeername(p, arg)); case LINUX_SOCKETPAIR: - return (linux_socketpair(p, args->args)); + return (linux_socketpair(p, arg)); case LINUX_SEND: - return (linux_send(p, args->args)); + return (linux_send(p, arg)); case LINUX_RECV: - return (linux_recv(p, args->args)); + return (linux_recv(p, arg)); case LINUX_SENDTO: - return (linux_sendto(p, args->args)); + return (linux_sendto(p, arg)); case LINUX_RECVFROM: - return (linux_recvfrom(p, args->args)); + return (linux_recvfrom(p, arg)); case LINUX_SHUTDOWN: - return (linux_shutdown(p, args->args)); + return (linux_shutdown(p, arg)); case LINUX_SETSOCKOPT: - return (linux_setsockopt(p, args->args)); + return (linux_setsockopt(p, arg)); case LINUX_GETSOCKOPT: - return (linux_getsockopt(p, args->args)); + return (linux_getsockopt(p, arg)); case LINUX_SENDMSG: do { int error; @@ -911,7 +912,7 @@ linux_socketcall(struct proc *p, struct linux_socketcall_args *args) int s; const struct msghdr *msg; int flags; - } *uap = args->args; + } *uap = arg; error = copyin(&uap->msg->msg_control, &control, sizeof(caddr_t)); @@ -939,10 +940,10 @@ linux_socketcall(struct proc *p, struct linux_socketcall_args *args) return (error); } done: - return (sendmsg(p, args->args)); + return (sendmsg(p, arg)); } while (0); case LINUX_RECVMSG: - return (linux_recvmsg(p, args->args)); + return (linux_recvmsg(p, arg)); } uprintf("LINUX: 'socket' typ=%d not implemented\n", args->what); diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c index 75364fb..5d1572b 100644 --- a/sys/compat/linux/linux_stats.c +++ b/sys/compat/linux/linux_stats.c @@ -37,6 +37,7 @@ #include <sys/mount.h> #include <sys/namei.h> #include <sys/stat.h> +#include <sys/sysctl.h> #include <sys/systm.h> #include <sys/vnode.h> @@ -44,93 +45,41 @@ #include <machine/../linux/linux_proto.h> #include <compat/linux/linux_util.h> -#include <sys/sysctl.h> - -struct linux_newstat { -#ifdef __alpha__ - u_int stat_dev; - u_int stat_ino; - u_int stat_mode; - u_int stat_nlink; - u_int stat_uid; - u_int stat_gid; - u_int stat_rdev; - long stat_size; - u_long stat_atime; - u_long stat_mtime; - u_long stat_ctime; - u_int stat_blksize; - int stat_blocks; - u_int stat_flags; - u_int stat_gen; -#else - u_short stat_dev; - u_short __pad1; - u_long stat_ino; - u_short stat_mode; - u_short stat_nlink; - u_short stat_uid; - u_short stat_gid; - u_short stat_rdev; - u_short __pad2; - u_long stat_size; - u_long stat_blksize; - u_long stat_blocks; - u_long stat_atime; - u_long __unused1; - u_long stat_mtime; - u_long __unused2; - u_long stat_ctime; - u_long __unused3; - u_long __unused4; - u_long __unused5; -#endif -}; - - -struct linux_ustat -{ - int f_tfree; - u_long f_tinode; - char f_fname[6]; - char f_fpack[6]; -}; - static int newstat_copyout(struct stat *buf, void *ubuf) { - struct linux_newstat tbuf; + struct l_newstat tbuf; struct cdevsw *cdevsw; dev_t dev; - tbuf.stat_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8); - tbuf.stat_ino = buf->st_ino; - tbuf.stat_mode = buf->st_mode; - tbuf.stat_nlink = buf->st_nlink; - tbuf.stat_uid = buf->st_uid; - tbuf.stat_gid = buf->st_gid; - tbuf.stat_rdev = buf->st_rdev; - tbuf.stat_size = buf->st_size; - tbuf.stat_atime = buf->st_atime; - tbuf.stat_mtime = buf->st_mtime; - tbuf.stat_ctime = buf->st_ctime; - tbuf.stat_blksize = buf->st_blksize; - tbuf.stat_blocks = buf->st_blocks; + tbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8); + tbuf.st_ino = buf->st_ino; + tbuf.st_mode = buf->st_mode; + tbuf.st_nlink = buf->st_nlink; + tbuf.st_uid = buf->st_uid; + tbuf.st_gid = buf->st_gid; + tbuf.st_rdev = buf->st_rdev; + tbuf.st_size = buf->st_size; + tbuf.st_atime = buf->st_atime; + tbuf.st_mtime = buf->st_mtime; + tbuf.st_ctime = buf->st_ctime; + tbuf.st_blksize = buf->st_blksize; + tbuf.st_blocks = buf->st_blocks; /* Lie about disk drives which are character devices * in FreeBSD but block devices under Linux. */ - if (S_ISCHR(tbuf.stat_mode) && + if (S_ISCHR(tbuf.st_mode) && (dev = udev2dev(buf->st_rdev, 0)) != NODEV) { cdevsw = devsw(dev); if (cdevsw != NULL && (cdevsw->d_flags & D_DISK)) { - tbuf.stat_mode &= ~S_IFMT; - tbuf.stat_mode |= S_IFBLK; + tbuf.st_mode &= ~S_IFMT; + tbuf.st_mode |= S_IFBLK; /* XXX this may not be quite right */ /* Map major number to 0 */ - tbuf.stat_dev = uminor(buf->st_dev) & 0xf; - tbuf.stat_rdev = buf->st_rdev & 0xff; + tbuf.st_dev = uminor(buf->st_dev) & 0xf; + tbuf.st_rdev = buf->st_rdev & 0xff; } } @@ -154,7 +103,7 @@ linux_newstat(struct proc *p, struct linux_newstat_args *args) #endif NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - args->path, p); + args->path, p); error = namei(&nd); if (error) return (error); @@ -168,42 +117,35 @@ linux_newstat(struct proc *p, struct linux_newstat_args *args) return (newstat_copyout(&buf, args->buf)); } -/* - * Get file status; this version does not follow links. - */ int -linux_newlstat(p, uap) - struct proc *p; - struct linux_newlstat_args *uap; +linux_newlstat(struct proc *p, struct linux_newlstat_args *args) { int error; - struct vnode *vp; struct stat sb; struct nameidata nd; caddr_t sg; sg = stackgap_init(); - CHECKALTEXIST(p, &sg, uap->path); + CHECKALTEXIST(p, &sg, args->path); #ifdef DEBUG if (ldebug(newlstat)) - printf(ARGS(newlstat, "%s, *"), uap->path); + printf(ARGS(newlstat, "%s, *"), args->path); #endif NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, - uap->path, p); + args->path, p); error = namei(&nd); if (error) return (error); NDFREE(&nd, NDF_ONLY_PNBUF); - vp = nd.ni_vp; - error = vn_stat(vp, &sb, p); - vput(vp); + error = vn_stat(nd.ni_vp, &sb, p); + vput(nd.ni_vp); if (error) return (error); - return (newstat_copyout(&sb, uap->buf)); + return (newstat_copyout(&sb, args->buf)); } int @@ -214,13 +156,12 @@ linux_newfstat(struct proc *p, struct linux_newfstat_args *args) struct stat buf; int error; - fdp = p->p_fd; - #ifdef DEBUG if (ldebug(newfstat)) printf(ARGS(newfstat, "%d, *"), args->fd); #endif + fdp = p->p_fd; if ((unsigned)args->fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[args->fd]) == NULL) return (EBADF); @@ -232,21 +173,22 @@ linux_newfstat(struct proc *p, struct linux_newfstat_args *args) return (error); } -struct linux_statfs_buf { - int ftype; - int fbsize; - int fblocks; - int fbfree; - int fbavail; - int ffiles; - int fffree; - linux_fsid_t ffsid; - int fnamelen; - int fspare[6]; +/* XXX - All fields of type l_int are defined as l_long on i386 */ +struct l_statfs { + l_int f_type; + l_int f_bsize; + l_int f_blocks; + l_int f_bfree; + l_int f_bavail; + l_int f_files; + l_int f_ffree; + l_fsid_t f_fsid; + l_int f_namelen; + l_int f_spare[6]; }; #ifndef VT_NWFS -#define VT_NWFS VT_TFS /* XXX - bug compatibility with sys/fs/nwfs/nwfs_node.h */ +#define VT_NWFS VT_TFS /* XXX - bug compat. with sys/fs/nwfs/nwfs_node.h */ #endif #define LINUX_CODA_SUPER_MAGIC 0x73757245L @@ -299,7 +241,7 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args) struct nameidata *ndp; struct statfs *bsd_statfs; struct nameidata nd; - struct linux_statfs_buf linux_statfs_buf; + struct l_statfs linux_statfs; int error; caddr_t sg; @@ -323,18 +265,18 @@ linux_statfs(struct proc *p, struct linux_statfs_args *args) if (error) return error; bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - linux_statfs_buf.ftype = bsd_to_linux_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)); + linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_type); + linux_statfs.f_bsize = bsd_statfs->f_bsize; + linux_statfs.f_blocks = bsd_statfs->f_blocks; + linux_statfs.f_bfree = bsd_statfs->f_bfree; + linux_statfs.f_bavail = bsd_statfs->f_bavail; + linux_statfs.f_ffree = bsd_statfs->f_ffree; + linux_statfs.f_files = bsd_statfs->f_files; + linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs.f_namelen = MAXNAMLEN; + return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, + sizeof(linux_statfs)); } int @@ -343,7 +285,7 @@ linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args) struct file *fp; struct mount *mp; struct statfs *bsd_statfs; - struct linux_statfs_buf linux_statfs_buf; + struct l_statfs linux_statfs; int error; #ifdef DEBUG @@ -359,26 +301,32 @@ linux_fstatfs(struct proc *p, struct linux_fstatfs_args *args) if (error) return error; bsd_statfs->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - linux_statfs_buf.ftype = bsd_to_linux_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)); + linux_statfs.f_type = bsd_to_linux_ftype(bsd_statfs->f_type); + linux_statfs.f_bsize = bsd_statfs->f_bsize; + linux_statfs.f_blocks = bsd_statfs->f_blocks; + linux_statfs.f_bfree = bsd_statfs->f_bfree; + linux_statfs.f_bavail = bsd_statfs->f_bavail; + linux_statfs.f_ffree = bsd_statfs->f_ffree; + linux_statfs.f_files = bsd_statfs->f_files; + linux_statfs.f_fsid.val[0] = bsd_statfs->f_fsid.val[0]; + linux_statfs.f_fsid.val[1] = bsd_statfs->f_fsid.val[1]; + linux_statfs.f_namelen = MAXNAMLEN; + return copyout((caddr_t)&linux_statfs, (caddr_t)args->buf, + sizeof(linux_statfs)); } +struct l_ustat +{ + l_daddr_t f_tfree; + l_ino_t f_tinode; + char f_fname[6]; + char f_fpack[6]; +}; + int -linux_ustat(p, uap) - struct proc *p; - struct linux_ustat_args *uap; +linux_ustat(struct proc *p, struct linux_ustat_args *args) { - struct linux_ustat lu; + struct l_ustat lu; dev_t dev; struct vnode *vp; struct statfs *stat; @@ -386,7 +334,7 @@ linux_ustat(p, uap) #ifdef DEBUG if (ldebug(ustat)) - printf(ARGS(ustat, "%d, *"), uap->dev); + printf(ARGS(ustat, "%d, *"), args->dev); #endif /* @@ -402,7 +350,7 @@ linux_ustat(p, uap) * dev_t returned from previous syscalls. Just return a bzeroed * ustat in that case. */ - dev = makedev(uap->dev >> 8, uap->dev & 0xFF); + dev = makedev(args->dev >> 8, args->dev & 0xFF); if (vfinddev(dev, VCHR, &vp)) { if (vp->v_mount == NULL) return (EINVAL); @@ -415,5 +363,127 @@ linux_ustat(p, uap) lu.f_tinode = stat->f_ffree; } - return (copyout(&lu, uap->ubuf, sizeof(lu))); + return (copyout(&lu, args->ubuf, sizeof(lu))); } + +#if defined(__i386__) + +static int +stat64_copyout(struct stat *buf, void *ubuf) +{ + struct l_stat64 lbuf; + + bzero(&lbuf, sizeof(lbuf)); + lbuf.st_dev = uminor(buf->st_dev) | (umajor(buf->st_dev) << 8); + lbuf.st_ino = buf->st_ino; + lbuf.st_mode = buf->st_mode; + lbuf.st_nlink = buf->st_nlink; + lbuf.st_uid = buf->st_uid; + lbuf.st_gid = buf->st_gid; + lbuf.st_rdev = buf->st_rdev; + lbuf.st_size = buf->st_size; + lbuf.st_atime = buf->st_atime; + lbuf.st_mtime = buf->st_mtime; + lbuf.st_ctime = buf->st_ctime; + lbuf.st_blksize = buf->st_blksize; + lbuf.st_blocks = buf->st_blocks; + + /* + * The __st_ino field makes all the difference. In the Linux kernel + * it is conditionally compiled based on STAT64_HAS_BROKEN_ST_INO, + * but without the assignment to __st_ino the runtime linker refuses + * to mmap(2) any shared libraries. I guess it's broken alright :-) + */ + lbuf.__st_ino = buf->st_ino; + + return (copyout(&lbuf, ubuf, sizeof(lbuf))); +} + +int +linux_stat64(struct proc *p, struct linux_stat64_args *args) +{ + struct stat buf; + struct nameidata nd; + int error; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->filename); + +#ifdef DEBUG + if (ldebug(stat64)) + printf(ARGS(stat64, "%s, *"), args->filename); +#endif + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->filename, p); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &buf, p); + vput(nd.ni_vp); + if (error) + return (error); + + return (stat64_copyout(&buf, args->statbuf)); +} + +int +linux_lstat64(struct proc *p, struct linux_lstat64_args *args) +{ + int error; + struct stat sb; + struct nameidata nd; + caddr_t sg; + + sg = stackgap_init(); + CHECKALTEXIST(p, &sg, args->filename); + +#ifdef DEBUG + if (ldebug(lstat64)) + printf(ARGS(lstat64, "%s, *"), args->filename); +#endif + + NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, + args->filename, p); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = vn_stat(nd.ni_vp, &sb, p); + vput(nd.ni_vp); + if (error) + return (error); + + return (stat64_copyout(&sb, args->statbuf)); +} + +int +linux_fstat64(struct proc *p, struct linux_fstat64_args *args) +{ + struct filedesc *fdp; + struct file *fp; + struct stat buf; + int error; + +#ifdef DEBUG + if (ldebug(fstat64)) + printf(ARGS(fstat64, "%d, *"), args->fd); +#endif + + fdp = p->p_fd; + if ((unsigned)args->fd >= fdp->fd_nfiles || + (fp = fdp->fd_ofiles[args->fd]) == NULL) + return (EBADF); + + error = fo_stat(fp, &buf, p); + if (!error) + error = stat64_copyout(&buf, args->statbuf); + + return (error); +} + +#endif /* __i386__ */ diff --git a/sys/compat/linux/linux_sysctl.c b/sys/compat/linux/linux_sysctl.c new file mode 100644 index 0000000..14c5a6f --- /dev/null +++ b/sys/compat/linux/linux_sysctl.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2001 Marcel Moolenaar + * 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 + * 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 + * 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. + * + * $FreeBSD$ + */ + +#include "opt_compat.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/sysproto.h> + +#include <machine/../linux/linux.h> +#include <machine/../linux/linux_proto.h> +#include <compat/linux/linux_util.h> + +#define LINUX_CTL_KERN 1 +#define LINUX_CTL_VM 2 +#define LINUX_CTL_NET 3 +#define LINUX_CTL_PROC 4 +#define LINUX_CTL_FS 5 +#define LINUX_CTL_DEBUG 6 +#define LINUX_CTL_DEV 7 +#define LINUX_CTL_BUS 8 + +/* CTL_KERN names */ +#define LINUX_KERN_OSTYPE 1 +#define LINUX_KERN_OSRELEASE 2 +#define LINUX_KERN_OSREV 3 +#define LINUX_KERN_VERSION 4 + +static int +handle_string(struct l___sysctl_args *la, char *value) +{ + int error; + + if (la->oldval != NULL) { + l_int len = strlen(value); + error = copyout(value, la->oldval, len + 1); + if (!error && la->oldlenp != NULL) + error = copyout(&len, la->oldlenp, sizeof(len)); + if (error) + return (error); + } + + if (la->newval != NULL) + return (ENOTDIR); + + return (0); +} + +int +linux_sysctl(struct proc *p, struct linux_sysctl_args *args) +{ + struct l___sysctl_args la; + l_int *mib; + int error, i; + caddr_t sg; + + error = copyin((caddr_t)args->args, &la, sizeof(la)); + if (error) + return (error); + + if (la.nlen == 0 || la.nlen > LINUX_CTL_MAXNAME) + return (ENOTDIR); + + sg = stackgap_init(); + mib = stackgap_alloc(&sg, la.nlen * sizeof(l_int)); + error = copyin(la.name, mib, la.nlen * sizeof(l_int)); + if (error) + return (error); + + switch (mib[0]) { + case LINUX_CTL_KERN: + if (la.nlen < 2) + break; + + switch (mib[1]) { + case LINUX_KERN_VERSION: + return (handle_string(&la, version)); + default: + break; + } + break; + default: + break; + } + + printf("linux: sysctl: unhandled name="); + for (i = 0; i < la.nlen; i++) + printf("%c%d", (i) ? ',' : '{', mib[i]); + printf("}\n"); + + return (ENOTDIR); +} |