summaryrefslogtreecommitdiffstats
path: root/sys/i386/linux/linux_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/linux/linux_file.c')
-rw-r--r--sys/i386/linux/linux_file.c397
1 files changed, 354 insertions, 43 deletions
diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c
index 0918f22..93932df 100644
--- a/sys/i386/linux/linux_file.c
+++ b/sys/i386/linux/linux_file.c
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: linux_file.c,v 1.4 1995/11/22 07:43:45 bde Exp $
+ * $Id: linux_file.c,v 1.5 1995/12/15 03:06:50 peter Exp $
*/
#include <sys/param.h>
@@ -41,16 +41,15 @@
#include <sys/malloc.h>
#include <sys/exec.h>
#include <sys/dirent.h>
+#include <sys/sysproto.h>
+#include <sys/conf.h>
+#include <sys/tty.h>
#include <ufs/ufs/dir.h>
#include <i386/linux/linux.h>
-#include <i386/linux/sysproto.h>
-
-struct linux_creat_args {
- char *path;
- int mode;
-};
+#include <i386/linux/linux_proto.h>
+#include <i386/linux/linux_util.h>
int
linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
@@ -60,6 +59,10 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
int flags;
int mode;
} */ bsd_open_args;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
#ifdef DEBUG
printf("Linux-emul(%d): creat(%s, %d)\n",
@@ -71,12 +74,6 @@ linux_creat(struct proc *p, struct linux_creat_args *args, int *retval)
return open(p, &bsd_open_args, retval);
}
-struct linux_open_args {
- char *path;
- int flags;
- int mode;
-};
-
int
linux_open(struct proc *p, struct linux_open_args *args, int *retval)
{
@@ -86,7 +83,15 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval)
int mode;
} */ bsd_open_args;
int error;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ if (args->flags & LINUX_O_CREAT)
+ CHECKALTCREAT(p, &sg, args->path);
+ else
+ CHECKALTEXIST(p, &sg, args->path);
+
#ifdef DEBUG
printf("Linux-emul(%d): open(%s, 0x%x, 0x%x)\n",
p->p_pid, args->path, args->flags, args->mode);
@@ -128,6 +133,10 @@ linux_open(struct proc *p, struct linux_open_args *args, int *retval)
if (fp->f_type == DTYPE_VNODE)
(fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t) 0, p);
}
+#ifdef DEBUG
+ printf("Linux-emul(%d): open returns error %d\n",
+ p->p_pid, error);
+#endif
return error;
}
@@ -179,12 +188,6 @@ bsd_to_linux_flock(struct flock *bsd_flock, struct linux_flock *linux_flock)
linux_flock->l_pid = (linux_pid_t)bsd_flock->l_pid;
}
-struct linux_fcntl_args {
- int fd;
- int cmd;
- int arg;
-};
-
int
linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
{
@@ -195,8 +198,19 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
int arg;
} */ fcntl_args;
struct linux_flock linux_flock;
- struct flock *bsd_flock =
- (struct flock *)ua_alloc_init(sizeof(struct flock));
+ struct flock *bsd_flock;
+ struct filedesc *fdp;
+ struct file *fp;
+ struct vnode *vp;
+ struct vattr va;
+ long pgid;
+ struct pgrp *pgrp;
+ struct tty *tp, *(*d_tty) __P((dev_t));
+ caddr_t sg;
+
+ sg = stackgap_init();
+ bsd_flock = (struct flock *)stackgap_alloc(&sg, sizeof(struct flock));
+ d_tty = NULL;
#ifdef DEBUG
printf("Linux-emul(%d): fcntl(%d, %08x, *)\n",
@@ -269,22 +283,51 @@ linux_fcntl(struct proc *p, struct linux_fcntl_args *args, int *retval)
return fcntl(p, &fcntl_args, retval);
case LINUX_F_SETOWN:
- fcntl_args.cmd = F_SETOWN;
- return fcntl(p, &fcntl_args, retval);
-
case LINUX_F_GETOWN:
- fcntl_args.cmd = F_GETOWN;
- return fcntl(p, &fcntl_args, retval);
+ /*
+ * We need to route around the normal fcntl() for these calls,
+ * since it uses TIOC{G,S}PGRP, which is too restrictive for
+ * Linux F_{G,S}ETOWN semantics. For sockets, this problem
+ * does not exist.
+ */
+ fdp = p->p_fd;
+ if ((u_int)args->fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[args->fd]) == NULL)
+ return EBADF;
+ if (fp->f_type == DTYPE_SOCKET) {
+ fcntl_args.cmd = args->cmd == LINUX_F_SETOWN ? F_SETOWN : F_GETOWN;
+ return fcntl(p, &fcntl_args, retval);
+ }
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VCHR)
+ return EINVAL;
+ if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
+ return error;
+
+ d_tty = cdevsw[major(va.va_rdev)]->d_devtotty;
+ if (!d_tty || (!(tp = (*d_tty)(va.va_rdev))))
+ return EINVAL;
+ if (args->cmd == LINUX_F_GETOWN) {
+ retval[0] = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
+ return 0;
+ }
+ if ((long)args->arg <= 0) {
+ pgid = -(long)args->arg;
+ } else {
+ struct proc *p1 = pfind((long)args->arg);
+ if (p1 == 0)
+ return (ESRCH);
+ pgid = (long)p1->p_pgrp->pg_id;
+ }
+ pgrp = pgfind(pgid);
+ if (pgrp == NULL || pgrp->pg_session != p->p_session)
+ return EPERM;
+ tp->t_pgrp = pgrp;
+ return 0;
}
return EINVAL;
}
-struct linux_lseek_args {
- int fdes;
- unsigned long off;
- int whence;
-};
-
int
linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
{
@@ -308,6 +351,34 @@ linux_lseek(struct proc *p, struct linux_lseek_args *args, int *retval)
return error;
}
+int
+linux_llseek(struct proc *p, struct linux_llseek_args *args, int *retval)
+{
+ struct lseek_args bsd_args;
+ int error;
+ off_t off;
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): llseek(%d, %d:%d, %d)\n",
+ p->p_pid, args->fd, args->ohigh, args->olow, args->whence);
+#endif
+ off = (args->olow) | (((off_t) args->ohigh) << 32);
+
+ bsd_args.fd = args->fd;
+ bsd_args.offset = off;
+ bsd_args.whence = args->whence;
+
+ if ((error = lseek(p, &bsd_args, retval)))
+ return error;
+
+ if ((error = copyout(retval, (caddr_t)args->res, sizeof (off_t))))
+ return error;
+
+ retval[0] = 0;
+ return 0;
+}
+
+
struct linux_dirent {
long dino;
linux_off_t doff;
@@ -318,15 +389,20 @@ struct linux_dirent {
#define LINUX_RECLEN(de,namlen) \
ALIGN((((char *)&(de)->dname - (char *)de) + (namlen) + 1))
-struct linux_readdir_args {
- int fd;
- struct linux_dirent *dent;
- unsigned int count;
-};
-
int
linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
{
+ struct linux_getdents_args lda;
+
+ lda.fd = args->fd;
+ lda.dent = args->dent;
+ lda.count = 1;
+ return linux_getdents(p, &lda, retval);
+}
+
+int
+linux_getdents(struct proc *p, struct linux_getdents_args *args, int *retval)
+{
register struct dirent *bdp;
struct vnode *vp;
caddr_t inp, buf; /* BSD-format */
@@ -342,12 +418,12 @@ linux_readdir(struct proc *p, struct linux_readdir_args *args, int *retval)
int buflen, error, eofflag, nbytes, justone, blockoff;
#ifdef DEBUG
- printf("Linux-emul(%d): readdir(%d, *, %d)\n",
+ printf("Linux-emul(%d): getdents(%d, *, %d)\n",
p->p_pid, args->fd, args->count);
#endif
if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) {
return (error);
-}
+ }
if ((fp->f_flag & FREAD) == 0)
return (EBADF);
@@ -390,7 +466,7 @@ again:
(u_int **) NULL);
if (error) {
goto out;
-}
+ }
inp = buf;
inp += blockoff;
@@ -398,7 +474,7 @@ again:
resid = nbytes;
if ((len = buflen - auio.uio_resid - blockoff) == 0) {
goto eof;
- }
+ }
while (len > 0) {
bdp = (struct dirent *) inp;
@@ -426,7 +502,7 @@ again:
strcpy(linux_dirent.dname, bdp->d_name);
if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
goto out;
- }
+ }
inp += reclen;
off += reclen;
outp += linuxreclen;
@@ -450,3 +526,238 @@ out:
free(buf, M_TEMP);
return error;
}
+
+/*
+ * These exist mainly for hooks for doing /compat/linux translation.
+ */
+
+int
+linux_access(struct proc *p, struct linux_access_args *args, int *retval)
+{
+ struct access_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): access(%s, %d)\n",
+ p->p_pid, args->path, args->flags);
+#endif
+ bsd.path = args->path;
+ bsd.flags = args->flags;
+
+ return access(p, &bsd, retval);
+}
+
+int
+linux_unlink(struct proc *p, struct linux_unlink_args *args, int *retval)
+{
+ struct unlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): unlink(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return unlink(p, &bsd, retval);
+}
+
+int
+linux_chdir(struct proc *p, struct linux_chdir_args *args, int *retval)
+{
+ struct chdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return chdir(p, &bsd, retval);
+}
+
+int
+linux_chmod(struct proc *p, struct linux_chmod_args *args, int *retval)
+{
+ struct chmod_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chmod(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return chmod(p, &bsd, retval);
+}
+
+int
+linux_chown(struct proc *p, struct linux_chown_args *args, int *retval)
+{
+ struct chown_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): chown(%s, %d, %d)\n",
+ p->p_pid, args->path, args->uid, args->gid);
+#endif
+ bsd.path = args->path;
+ /* XXX size casts here */
+ bsd.uid = args->uid;
+ bsd.gid = args->gid;
+
+ return chown(p, &bsd, retval);
+}
+
+int
+linux_mkdir(struct proc *p, struct linux_mkdir_args *args, int *retval)
+{
+ struct mkdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTCREAT(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): mkdir(%s, %d)\n",
+ p->p_pid, args->path, args->mode);
+#endif
+ bsd.path = args->path;
+ bsd.mode = args->mode;
+
+ return mkdir(p, &bsd, retval);
+}
+
+int
+linux_rmdir(struct proc *p, struct linux_rmdir_args *args, int *retval)
+{
+ struct rmdir_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rmdir(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return rmdir(p, &bsd, retval);
+}
+
+int
+linux_rename(struct proc *p, struct linux_rename_args *args, int *retval)
+{
+ struct rename_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->from);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): rename(%s, %s)\n",
+ p->p_pid, args->from, args->to);
+#endif
+ bsd.from = args->from;
+ bsd.to = args->to;
+
+ return rename(p, &bsd, retval);
+}
+
+int
+linux_symlink(struct proc *p, struct linux_symlink_args *args, int *retval)
+{
+ struct symlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+ CHECKALTCREAT(p, &sg, args->to);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): symlink(%s, %s)\n",
+ p->p_pid, args->path, args->to);
+#endif
+ bsd.path = args->path;
+ bsd.link = args->to;
+
+ return symlink(p, &bsd, retval);
+}
+
+int
+linux_execve(struct proc *p, struct linux_execve_args *args, int *retval)
+{
+ struct execve_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): execve(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.fname = args->path;
+ bsd.argv = args->argp;
+ bsd.envv = args->envp;
+
+ return execve(p, &bsd, retval);
+}
+
+int
+linux_readlink(struct proc *p, struct linux_readlink_args *args, int *retval)
+{
+ struct readlink_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->name);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): readlink(%s, 0x%x, %d)\n",
+ p->p_pid, args->name, args->buf, args->count);
+#endif
+ bsd.path = args->name;
+ bsd.buf = args->buf;
+ bsd.count = args->count;
+
+ return readlink(p, &bsd, retval);
+}
+
+int
+linux_truncate(struct proc *p, struct linux_truncate_args *args, int *retval)
+{
+ struct otruncate_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ printf("Linux-emul(%d): truncate(%s)\n",
+ p->p_pid, args->path);
+#endif
+ bsd.path = args->path;
+
+ return otruncate(p, &bsd, retval);
+}
+
OpenPOWER on IntegriCloud