Emulate some syscalls that appear in Linux 1.3: a select() with normal args,
getdents() and flock().
This commit is contained in:
parent
d6160bdc1b
commit
28d9d64235
|
@ -1,4 +1,4 @@
|
|||
$NetBSD: syscalls.master,v 1.9 1995/08/21 03:42:12 mycroft Exp $
|
||||
$NetBSD: syscalls.master,v 1.10 1995/08/23 20:17:30 fvdl Exp $
|
||||
|
||||
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
|
||||
|
||||
|
@ -130,7 +130,7 @@
|
|||
struct timezone *tzp); }
|
||||
80 NOARGS { int getgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
81 NOARGS { int setgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
82 STD { int linux_select(struct linux_select *lsp); }
|
||||
82 STD { int linux_oldselect(struct linux_select *lsp); }
|
||||
83 STD { int linux_symlink(char *path, char *to); }
|
||||
84 NOARGS { int compat_43_lstat(char *path, struct ostat *up); }
|
||||
85 STD { int linux_readlink(char *name, char *buf, int count); }
|
||||
|
@ -201,3 +201,9 @@
|
|||
139 UNIMPL linux_getfsuid
|
||||
140 STD { int linux_llseek(int fd, u_int32_t ohigh, \
|
||||
u_int32_t olow, caddr_t res, int whence); }
|
||||
141 STD { int linux_getdents(int fd, void *dirent, \
|
||||
unsigned count); }
|
||||
142 STD { int linux_select(int nfds, fd_set *readfds, \
|
||||
fd_set *writefds, fd_set *exceptfds, \
|
||||
struct timeval *timeout); }
|
||||
143 NOARGS { int flock(int fd, int how); }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_break.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_break.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_misc.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_misc.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_misc_notalpha.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_misc_notalpha.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldmmap.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldmmap.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldolduname.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldolduname.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldselect.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldselect.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_olduname.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_olduname.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_pipe.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_pipe.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$NetBSD: syscalls.master,v 1.9 1995/08/21 03:42:12 mycroft Exp $
|
||||
$NetBSD: syscalls.master,v 1.10 1995/08/23 20:17:30 fvdl Exp $
|
||||
|
||||
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
|
||||
|
||||
|
@ -130,7 +130,7 @@
|
|||
struct timezone *tzp); }
|
||||
80 NOARGS { int getgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
81 NOARGS { int setgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
82 STD { int linux_select(struct linux_select *lsp); }
|
||||
82 STD { int linux_oldselect(struct linux_select *lsp); }
|
||||
83 STD { int linux_symlink(char *path, char *to); }
|
||||
84 NOARGS { int compat_43_lstat(char *path, struct ostat *up); }
|
||||
85 STD { int linux_readlink(char *name, char *buf, int count); }
|
||||
|
@ -201,3 +201,9 @@
|
|||
139 UNIMPL linux_getfsuid
|
||||
140 STD { int linux_llseek(int fd, u_int32_t ohigh, \
|
||||
u_int32_t olow, caddr_t res, int whence); }
|
||||
141 STD { int linux_getdents(int fd, void *dirent, \
|
||||
unsigned count); }
|
||||
142 STD { int linux_select(int nfds, fd_set *readfds, \
|
||||
fd_set *writefds, fd_set *exceptfds, \
|
||||
struct timeval *timeout); }
|
||||
143 NOARGS { int flock(int fd, int how); }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_misc.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_misc.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_break.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_break.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_misc_notalpha.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_misc_notalpha.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldmmap.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldmmap.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldolduname.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldolduname.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_oldselect.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_oldselect.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_olduname.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_olduname.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_pipe.c,v 1.16 1995/08/21 23:15:51 fvdl Exp $ */
|
||||
/* $NetBSD: linux_pipe.c,v 1.17 1995/08/23 20:17:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Frank van der Linden
|
||||
|
@ -677,20 +677,46 @@ linux_utime(p, uap, retval)
|
|||
return utimes(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* The old Linux readdir was only able to read one entry at a time,
|
||||
* even though it had a 'count' argument. In fact, the emulation
|
||||
* of the old call was better than the original, because it did handle
|
||||
* the count arg properly. Don't bother with it anymore now, and use
|
||||
* it to distinguish between old and new. The difference is that the
|
||||
* newer one actually does multiple entries, and the reclen field
|
||||
* really is the reclen, not the namelength.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
syscallarg(struct linux_dirent *) dent;
|
||||
syscallarg(unsigned int) count;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
|
||||
SCARG(uap, count) = 1;
|
||||
return linux_getdents(p, uap, retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Linux 'readdir' call. This code is mostly taken from the
|
||||
* SunOS getdents call (see compat/sunos/sunos_misc.c), though
|
||||
* an attempt has been made to keep it a little cleaner (failing
|
||||
* miserably, because of the cruft needed if count 1 is passed).
|
||||
*
|
||||
* The d_off field should contain the offset of the next valid entry,
|
||||
* but in Linux it has the offset of the entry itself. We emulate
|
||||
* that bug here.
|
||||
*
|
||||
* Read in BSD-style entries, convert them, and copy them out.
|
||||
* Note that the Linux d_reclen is actually the name length,
|
||||
* and d_off is the reclen.
|
||||
*
|
||||
* Note that this doesn't handle union-mounted filesystems.
|
||||
*/
|
||||
int
|
||||
linux_readdir(p, uap, retval)
|
||||
linux_getdents(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_readdir_args /* {
|
||||
syscallarg(int) fd;
|
||||
|
@ -711,7 +737,7 @@ linux_readdir(p, uap, retval)
|
|||
struct linux_dirent idb;
|
||||
off_t off; /* true file offset */
|
||||
linux_off_t soff; /* Linux file offset */
|
||||
int buflen, error, eofflag, nbytes, justone;
|
||||
int buflen, error, eofflag, nbytes, oldcall;
|
||||
struct vattr va;
|
||||
|
||||
if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
|
||||
|
@ -729,13 +755,13 @@ linux_readdir(p, uap, retval)
|
|||
return error;
|
||||
|
||||
nbytes = SCARG(uap, count);
|
||||
if (nbytes == 1) { /* Need this for older Linux libs, apparently */
|
||||
if (nbytes == 1) { /* emulating old, broken behaviour */
|
||||
nbytes = sizeof (struct linux_dirent);
|
||||
buflen = max(va.va_blocksize, nbytes);
|
||||
justone = 1;
|
||||
oldcall = 1;
|
||||
} else {
|
||||
buflen = min(MAXBSIZE, nbytes);
|
||||
justone = 0;
|
||||
oldcall = 0;
|
||||
}
|
||||
buf = malloc(buflen, M_TEMP, M_WAITOK);
|
||||
VOP_LOCK(vp);
|
||||
|
@ -769,7 +795,6 @@ again:
|
|||
reclen = bdp->d_reclen;
|
||||
if (reclen & 3)
|
||||
panic("linux_readdir");
|
||||
off += reclen; /* each entry points to next */
|
||||
if (bdp->d_fileno == 0) {
|
||||
inp += reclen; /* it is a hole; squish it out */
|
||||
continue;
|
||||
|
@ -786,17 +811,21 @@ again:
|
|||
* the copyout() call).
|
||||
*/
|
||||
idb.d_ino = (long)bdp->d_fileno;
|
||||
idb.d_off = (linux_off_t)linuxreclen;
|
||||
idb.d_reclen = (u_short)bdp->d_namlen;
|
||||
idb.d_off = off;
|
||||
/*
|
||||
* The old readdir() call used the reclen field as namlen.
|
||||
*/
|
||||
idb.d_reclen = oldcall ? (u_short)bdp->d_namlen : linuxreclen;
|
||||
strcpy(idb.d_name, bdp->d_name);
|
||||
if ((error = copyout((caddr_t)&idb, outp, linuxreclen)))
|
||||
goto out;
|
||||
/* advance past this real entry */
|
||||
inp += reclen;
|
||||
off += reclen;
|
||||
/* advance output past Linux-shaped entry */
|
||||
outp += linuxreclen;
|
||||
resid -= linuxreclen;
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -805,7 +834,7 @@ again:
|
|||
goto again;
|
||||
fp->f_offset = off; /* update the vnode offset */
|
||||
|
||||
if (justone)
|
||||
if (oldcall)
|
||||
nbytes = resid + linuxreclen;
|
||||
|
||||
eof:
|
||||
|
@ -817,38 +846,80 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* Out of register error once more.. Also, Linux copies the amount of
|
||||
* time left into the user-supplied timeval structure.
|
||||
* Not sure why the arguments to this older version of select() were put
|
||||
* into a structure, because there are 5, and that can all be handled
|
||||
* in registers on the i386 like Linux wants to.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
linux_oldselect(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
struct linux_oldselect_args /* {
|
||||
syscallarg(struct linux_select *) lsp;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
struct linux_select ls;
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
if ((error = copyin(SCARG(uap, lsp), &ls, sizeof(ls))))
|
||||
return error;
|
||||
|
||||
SCARG(&bsa, nd) = ls.nfds;
|
||||
SCARG(&bsa, in) = ls.readfds;
|
||||
SCARG(&bsa, ou) = ls.writefds;
|
||||
SCARG(&bsa, ex) = ls.exceptfds;
|
||||
SCARG(&bsa, tv) = ls.timeout;
|
||||
return linux_select1(p, retval, ls.nfds, ls.readfds, ls.writefds,
|
||||
ls.exceptfds, ls.timeout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Even when just using registers to pass arguments to syscalls you can
|
||||
* have 5 of them on the i386. So this newer version of select() does
|
||||
* this.
|
||||
*/
|
||||
int
|
||||
linux_select(p, uap, retval)
|
||||
struct proc *p;
|
||||
struct linux_select_args /* {
|
||||
syscallarg(int) nfds;
|
||||
syscallarg(fd_set *) readfds;
|
||||
syscallarg(fd_set *) writefds;
|
||||
syscallarg(fd_set *) exceptfds;
|
||||
syscallarg(struct timeval *) timeout;
|
||||
} */ *uap;
|
||||
register_t *retval;
|
||||
{
|
||||
return linux_select1(p, retval, SCARG(uap, nfds), SCARG(uap, readfds),
|
||||
SCARG(uap, writefds), SCARG(uap, exceptfds), SCARG(uap, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Common code for the old and new versions of select(). A couple of
|
||||
* things are important:
|
||||
* 1) return the amount of time left in the 'timeout' parameter
|
||||
* 2) select never returns ERESTART on Linux, always return EINTR
|
||||
*/
|
||||
int
|
||||
linux_select1(p, retval, nfds, readfds, writefds, exceptfds, timeout)
|
||||
struct proc *p;
|
||||
register_t *retval;
|
||||
int nfds;
|
||||
fd_set *readfds, *writefds, *exceptfds;
|
||||
struct timeval *timeout;
|
||||
{
|
||||
struct select_args bsa;
|
||||
struct timeval tv0, tv1, utv, *tvp;
|
||||
caddr_t sg;
|
||||
int error;
|
||||
|
||||
SCARG(&bsa, nd) = nfds;
|
||||
SCARG(&bsa, in) = readfds;
|
||||
SCARG(&bsa, ou) = writefds;
|
||||
SCARG(&bsa, ex) = exceptfds;
|
||||
SCARG(&bsa, tv) = timeout;
|
||||
|
||||
/*
|
||||
* Store current time for computation of the amount of
|
||||
* time left.
|
||||
*/
|
||||
if (ls.timeout) {
|
||||
if ((error = copyin(ls.timeout, &utv, sizeof(utv))))
|
||||
if (timeout) {
|
||||
if ((error = copyin(timeout, &utv, sizeof(utv))))
|
||||
return error;
|
||||
if (itimerfix(&utv)) {
|
||||
/*
|
||||
|
@ -883,7 +954,7 @@ linux_select(p, uap, retval)
|
|||
return error;
|
||||
}
|
||||
|
||||
if (ls.timeout) {
|
||||
if (timeout) {
|
||||
if (*retval) {
|
||||
/*
|
||||
* Compute how much time was left of the timeout,
|
||||
|
@ -898,7 +969,7 @@ linux_select(p, uap, retval)
|
|||
timerclear(&utv);
|
||||
} else
|
||||
timerclear(&utv);
|
||||
if ((error = copyout(&utv, ls.timeout, sizeof(utv))))
|
||||
if ((error = copyout(&utv, timeout, sizeof(utv))))
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$NetBSD: syscalls.master,v 1.9 1995/08/21 03:42:12 mycroft Exp $
|
||||
$NetBSD: syscalls.master,v 1.10 1995/08/23 20:17:30 fvdl Exp $
|
||||
|
||||
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
|
||||
|
||||
|
@ -130,7 +130,7 @@
|
|||
struct timezone *tzp); }
|
||||
80 NOARGS { int getgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
81 NOARGS { int setgroups(u_int gidsetsize, gid_t *gidset); }
|
||||
82 STD { int linux_select(struct linux_select *lsp); }
|
||||
82 STD { int linux_oldselect(struct linux_select *lsp); }
|
||||
83 STD { int linux_symlink(char *path, char *to); }
|
||||
84 NOARGS { int compat_43_lstat(char *path, struct ostat *up); }
|
||||
85 STD { int linux_readlink(char *name, char *buf, int count); }
|
||||
|
@ -201,3 +201,9 @@
|
|||
139 UNIMPL linux_getfsuid
|
||||
140 STD { int linux_llseek(int fd, u_int32_t ohigh, \
|
||||
u_int32_t olow, caddr_t res, int whence); }
|
||||
141 STD { int linux_getdents(int fd, void *dirent, \
|
||||
unsigned count); }
|
||||
142 STD { int linux_select(int nfds, fd_set *readfds, \
|
||||
fd_set *writefds, fd_set *exceptfds, \
|
||||
struct timeval *timeout); }
|
||||
143 NOARGS { int flock(int fd, int how); }
|
||||
|
|
Loading…
Reference in New Issue