diff options
| author | Peter Wemm <peter@FreeBSD.org> | 1996-03-02 19:38:20 +0000 | 
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 1996-03-02 19:38:20 +0000 | 
| commit | d66a506616078adf4d266a309f979ffd95fe634f (patch) | |
| tree | 83b4d342a731e2a76c19f214d574f24753abe420 /sys/i386/linux/linux_file.c | |
| parent | 9a074e93b595e10edfd4c6fd6bdacc61879fe381 (diff) | |
Notes
Diffstat (limited to 'sys/i386/linux/linux_file.c')
| -rw-r--r-- | sys/i386/linux/linux_file.c | 397 | 
1 files changed, 354 insertions, 43 deletions
diff --git a/sys/i386/linux/linux_file.c b/sys/i386/linux/linux_file.c index 0918f221fd3f..93932dfca75f 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); +} +  | 
