summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_file.c945
-rw-r--r--sys/compat/linux/linux_ioctl.c6
-rw-r--r--sys/compat/linux/linux_ipc.c225
-rw-r--r--sys/compat/linux/linux_ipc.h92
-rw-r--r--sys/compat/linux/linux_mib.c2
-rw-r--r--sys/compat/linux/linux_misc.c1309
-rw-r--r--sys/compat/linux/linux_signal.c62
-rw-r--r--sys/compat/linux/linux_signal.h8
-rw-r--r--sys/compat/linux/linux_socket.c39
-rw-r--r--sys/compat/linux/linux_stats.c336
-rw-r--r--sys/compat/linux/linux_sysctl.c120
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);
+}
OpenPOWER on IntegriCloud