Deleted Added
full compact
28c28
< * $FreeBSD: head/sys/compat/linux/linux_file.c 82518 2001-08-29 19:05:27Z gallatin $
---
> * $FreeBSD: head/sys/compat/linux/linux_file.c 83221 2001-09-08 19:07:04Z marcel $
152,202d151
< 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;
< }
<
204,321d152
< 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
336c167
< args->fdes, args->off, args->whence);
---
> args->fdes, (long)args->off, args->whence);
375,385d205
<
< 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))
<
399,400c219,250
< int
< linux_getdents(struct proc *p, struct linux_getdents_args *args)
---
> /*
> * 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...
> */
>
> struct l_dirent {
> l_long d_ino;
> l_off_t d_off;
> l_ushort d_reclen;
> char d_name[LINUX_NAME_MAX + 1];
> };
>
> 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];
> };
>
> #define LINUX_RECLEN(de,namlen) \
> ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
>
> #define LINUX_DIRBLKSIZ 512
>
> static int
> getdents_common(struct proc *p, struct linux_getdents64_args *args,
> int is64bit)
402,416c252,267
< 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;
---
> 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;
418,424c269,270
< #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);
< }
---
> if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0)
> return (error);
426,427c272,273
< if ((fp->f_flag & FREAD) == 0)
< return (EBADF);
---
> if ((fp->f_flag & FREAD) == 0)
> return (EBADF);
429c275,277
< vp = (struct vnode *) fp->f_data;
---
> vp = (struct vnode *) fp->f_data;
> if (vp->v_type != VDIR)
> return (EINVAL);
431,432c279,280
< if (vp->v_type != VDIR)
< return (EINVAL);
---
> if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)))
> return (error);
434,436c282,290
< 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;
438,444c292
< nbytes = args->count;
< if (nbytes == 1) {
< nbytes = sizeof (struct linux_dirent);
< justone = 1;
< }
< else
< justone = 0;
---
> off = fp->f_offset;
446,451c294,298
< 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);
---
> buflen = max(LINUX_DIRBLKSIZ, nbytes);
> buflen = min(buflen, MAXBSIZE);
> buf = malloc(buflen, M_TEMP, M_WAITOK);
> vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
>
453,461c300,308
< 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;
---
> 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;
463,466c310,313
< if (cookies) {
< free(cookies, M_TEMP);
< cookies = NULL;
< }
---
> if (cookies) {
> free(cookies, M_TEMP);
> cookies = NULL;
> }
468,471c315,317
< error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies);
< if (error) {
< goto out;
< }
---
> if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
> &cookies)))
> goto out;
473,478c319,323
< inp = buf;
< outp = (caddr_t) args->dent;
< resid = nbytes;
< if ((len = buflen - auio.uio_resid) <= 0) {
< goto eof;
< }
---
> inp = buf;
> outp = (caddr_t)args->dirent;
> resid = nbytes;
> if ((len = buflen - auio.uio_resid) <= 0)
> goto eof;
480c325
< cookiep = cookies;
---
> cookiep = cookies;
482,495c327,341
< 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--;
---
> 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--;
> }
497d342
< }
499,507c344,419
< 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;
---
> 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;
509,554d420
<
< 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;
< }
< 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;
< }
< strcpy(linux_dirent.dname, bdp->d_name);
< if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) {
< goto out;
< }
< inp += reclen;
< if (cookiep) {
< off = *cookiep++;
< ncookies--;
< } else
< off += reclen;
< outp += linuxreclen;
< resid -= linuxreclen;
< len -= reclen;
< if (justone)
< break;
< }
556,558c422,423
< if (outp == (caddr_t) args->dent)
< goto again;
< fp->f_offset = off;
---
> if (outp == (caddr_t)args->dirent)
> goto again;
560,561c425,427
< if (justone)
< nbytes = resid + linuxreclen;
---
> fp->f_offset = off;
> if (justone)
> nbytes = resid + linuxreclen;
564c430,431
< p->p_retval[0] = nbytes - resid;
---
> p->p_retval[0] = nbytes - resid;
>
566,570c433,438
< 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);
572a441,464
> 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));
> }
>
652,695d543
< 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
804c652,653
< printf(ARGS(truncate, "%s, %ld"), args->path, args->length);
---
> printf(ARGS(truncate, "%s, %ld"), args->path,
> (long)args->length);
940c789
< linux_umount(struct proc *p, struct linux_umount_args *args)
---
> linux_oldumount(struct proc *p, struct linux_oldumount_args *args)
942c791
< struct linux_umount2_args args2;
---
> struct linux_umount_args args2;
946c795
< return (linux_umount2(p, &args2));
---
> return (linux_umount(p, &args2));
950c799
< linux_umount2(struct proc *p, struct linux_umount2_args *args)
---
> linux_umount(struct proc *p, struct linux_umount_args *args)
957a807,1128
>
> /*
> * 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__ */