diff --git a/stand/libsa/close.c b/stand/libsa/close.c index d8f62fef6198..a177eb85eb3a 100644 --- a/stand/libsa/close.c +++ b/stand/libsa/close.c @@ -1,97 +1,112 @@ /* $NetBSD: close.c,v 1.7 1997/01/22 00:38:09 cgd Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)close.c 8.1 (Berkeley) 6/11/93 * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" int close(int fd) { - struct open_file *f = &files[fd]; + struct open_file *f, *last; int err1 = 0, err2 = 0; - if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { + f = fd2open_file(fd); + if (f == NULL) { errno = EBADF; return (-1); } free(f->f_rabuf); f->f_rabuf = NULL; - if (!(f->f_flags & F_RAW) && f->f_ops) - err1 = (f->f_ops->fo_close)(f); - if (!(f->f_flags & F_NODEV) && f->f_dev) - err2 = (f->f_dev->dv_close)(f); - if (f->f_devdata != NULL) - devclose(f); - f->f_flags = 0; + if (f->f_flags != 0) { + if (!(f->f_flags & F_RAW) && f->f_ops) + err1 = (f->f_ops->fo_close)(f); + if (!(f->f_flags & F_NODEV) && f->f_dev) + err2 = (f->f_dev->dv_close)(f); + if (f->f_devdata != NULL) + devclose(f); + f->f_flags = 0; + } else { + /* Attempt to close already closed file. */ + err1 = EBADF; + } + + /* free unused entries from tail. */ + TAILQ_FOREACH_REVERSE_SAFE(last, &files, file_list, f_link, f) { + if (last->f_flags != 0) + break; + TAILQ_REMOVE(&files, last, f_link); + free(last); + } + if (err1) { errno = err1; return (-1); } if (err2) { errno = err2; return (-1); } return (0); } diff --git a/stand/libsa/closeall.c b/stand/libsa/closeall.c index 9693130ebf9b..92c6955cf5da 100644 --- a/stand/libsa/closeall.c +++ b/stand/libsa/closeall.c @@ -1,76 +1,48 @@ -/* $NetBSD: closeall.c,v 1.1 1996/01/13 22:25:36 leo Exp $ */ - /*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * - * This code is derived from software contributed to Berkeley by - * The Mach Operating System project at Carnegie-Mellon University. + * Copyright (c) 2021 Toomas Soome * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)close.c 8.1 (Berkeley) 6/11/93 - * - * - * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University - * All Rights Reserved. - * - * Author: Alessandro Forin - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" void -closeall() +closeall(void) { - int i; + struct open_file *f; - for (i = 0; i < SOPEN_MAX; i++) - if (files[i].f_flags != 0) - (void)close(i); + /* + * Pick up last entry and close it, this will also trigger + * the removal of this entry, and we end up with empty list. + */ + while ((f = TAILQ_LAST(&files, file_list)) != NULL) { + (void)close(f->f_id); + } + /* reset errno from close() */ + errno = 0; } diff --git a/stand/libsa/fstat.c b/stand/libsa/fstat.c index cb2df8cbf0ac..47893416e0bf 100644 --- a/stand/libsa/fstat.c +++ b/stand/libsa/fstat.c @@ -1,61 +1,60 @@ /* $NetBSD: fstat.c,v 1.1 1996/01/13 22:25:38 leo Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stat.c 8.1 (Berkeley) 6/11/93 */ #include __FBSDID("$FreeBSD$"); #include "stand.h" int -fstat(fd, sb) - int fd; - struct stat *sb; +fstat(int fd, struct stat *sb) { - struct open_file *f = &files[fd]; + struct open_file *f; - if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { + f = fd2open_file(fd); + if (f == NULL || f->f_flags == 0) { errno = EBADF; return (-1); } /* operation not defined on raw devices */ if (f->f_flags & F_RAW) { errno = EOPNOTSUPP; return (-1); } errno = (f->f_ops->fo_stat)(f, sb); if (errno) return (-1); return (0); } diff --git a/stand/libsa/ioctl.c b/stand/libsa/ioctl.c index 807b308e5e50..7363236ada0e 100644 --- a/stand/libsa/ioctl.c +++ b/stand/libsa/ioctl.c @@ -1,88 +1,86 @@ /* $NetBSD: ioctl.c,v 1.4 1994/10/30 21:48:24 cgd Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ioctl.c 8.1 (Berkeley) 6/11/93 - * + * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin - * + * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. - * + * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * + * * Carnegie Mellon requests users of this software to return to - * + * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 - * + * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" int -ioctl(fd, cmd, arg) - int fd; - u_long cmd; - char *arg; +ioctl(int fd, u_long cmd, char *arg) { - struct open_file *f = &files[fd]; + struct open_file *f; - if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { + f = fd2open_file(fd); + if (f == NULL || f->f_flags == 0) { errno = EBADF; return (-1); } if (f->f_flags & F_RAW) { errno = (f->f_dev->dv_ioctl)(f, cmd, arg); if (errno) return (-1); return (0); } errno = EIO; return (-1); } diff --git a/stand/libsa/iodesc.h b/stand/libsa/iodesc.h index 37ae044af9d9..199fbcf74e98 100644 --- a/stand/libsa/iodesc.h +++ b/stand/libsa/iodesc.h @@ -1,52 +1,54 @@ /* $NetBSD: iodesc.h,v 1.4 1995/09/23 03:31:50 gwr Exp $ */ /* * Copyright (c) 1993 Adam Glass * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef __SYS_LIBNETBOOT_IODESC_H #define __SYS_LIBNETBOOT_IODESC_H struct iodesc { struct in_addr destip; /* dest. ip addr, net order */ struct in_addr myip; /* local ip addr, net order */ u_short destport; /* dest. port, net order */ u_short myport; /* local port, net order */ u_long xid; /* transaction identification */ u_char myea[6]; /* my ethernet address */ struct netif *io_netif; + int io_id; /* descriptor id */ + TAILQ_ENTRY(iodesc) io_link; /* next entry in list */ }; #endif /* __SYS_LIBNETBOOT_IODESC_H */ diff --git a/stand/libsa/lseek.c b/stand/libsa/lseek.c index 1a39eb31421b..c4ca97b148d6 100644 --- a/stand/libsa/lseek.c +++ b/stand/libsa/lseek.c @@ -1,142 +1,143 @@ /* $NetBSD: lseek.c,v 1.4 1997/01/22 00:38:10 cgd Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)lseek.c 8.1 (Berkeley) 6/11/93 * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" off_t lseek(int fd, off_t offset, int where) { off_t bufpos, filepos, target; - struct open_file *f = &files[fd]; + struct open_file *f; - if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) { + f = fd2open_file(fd); + if (f == NULL || f->f_flags == 0) { errno = EBADF; return (-1); } if (f->f_flags & F_RAW) { /* * On RAW devices, update internal offset. */ switch (where) { case SEEK_SET: f->f_offset = offset; break; case SEEK_CUR: f->f_offset += offset; break; default: errno = EOFFSET; return (-1); } return (f->f_offset); } /* * If there is some unconsumed data in the readahead buffer and it * contains the desired offset, simply adjust the buffer offset and * length. We don't bother with SEEK_END here, since the code to * handle it would fail in the same cases where the non-readahead * code fails (namely, for streams which cannot seek backward and whose * size isn't known in advance). */ if (f->f_ralen != 0 && where != SEEK_END) { filepos = (f->f_ops->fo_seek)(f, 0, SEEK_CUR); if (filepos == -1) return (-1); bufpos = filepos - f->f_ralen; switch (where) { case SEEK_SET: target = offset; break; case SEEK_CUR: target = bufpos + offset; break; default: errno = EINVAL; return (-1); } if (bufpos <= target && target < filepos) { f->f_raoffset += target - bufpos; f->f_ralen -= target - bufpos; return (target); } } /* * If this is a relative seek, we need to correct the offset for * bytes that we have already read but the caller doesn't know * about. */ if (where == SEEK_CUR) offset -= f->f_ralen; /* * Invalidate the readahead buffer. */ f->f_ralen = 0; return (f->f_ops->fo_seek)(f, offset, where); } diff --git a/stand/libsa/net.h b/stand/libsa/net.h index 36b7cacc95ef..77a11c8dcab6 100644 --- a/stand/libsa/net.h +++ b/stand/libsa/net.h @@ -1,133 +1,131 @@ /* $NetBSD: net.h,v 1.10 1995/10/20 00:46:30 cgd Exp $ */ /* * Copyright (c) 1993 Adam Glass * Copyright (c) 1992 Regents of the University of California. * All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _STAND_NET_H #define _STAND_NET_H #ifndef _KERNEL /* XXX - see */ #undef __IPADDR #define __IPADDR(x) htonl((uint32_t)(x)) #endif #include "iodesc.h" #define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } enum net_proto { NET_NONE, NET_NFS, NET_TFTP }; /* Returns true if n_long's on the same net */ #define SAMENET(a1, a2, m) ((a1.s_addr & m) == (a2.s_addr & m)) #define MACPY(s, d) bcopy((char *)s, (char *)d, 6) #define MAXTMO 120 /* seconds */ #define MINTMO 2 /* seconds */ #define FNAME_SIZE 128 #define IFNAME_SIZE 16 #define RECV_SIZE 1536 /* XXX delete this */ /* * How much room to leave for headers: * 14: struct ether_header * 20: struct ip * 8: struct udphdr * That's 42 but let's pad it out to 48 bytes. */ #define ETHER_SIZE 14 #define HEADER_SIZE 48 extern u_char bcea[6]; extern char rootpath[FNAME_SIZE]; extern char bootfile[FNAME_SIZE]; extern char hostname[FNAME_SIZE]; extern int hostnamelen; extern char domainname[FNAME_SIZE]; extern int domainnamelen; extern int netproto; extern char ifname[IFNAME_SIZE]; /* All of these are in network order. */ extern struct in_addr myip; extern struct in_addr rootip; extern struct in_addr swapip; extern struct in_addr gateip; extern struct in_addr nameip; extern struct in_addr servip; extern n_long netmask; extern u_int intf_mtu; extern int debug; /* defined in the machdep sources */ -extern struct iodesc sockets[SOPEN_MAX]; - /* ARP/RevARP functions: */ u_char *arpwhohas(struct iodesc *, struct in_addr); void arp_reply(struct iodesc *, void *); int rarp_getipaddress(int); /* Link functions: */ ssize_t sendether(struct iodesc *d, void *pkt, size_t len, u_char *dea, int etype); ssize_t readether(struct iodesc *, void **, void **, time_t, uint16_t *); ssize_t sendip(struct iodesc *, void *, size_t, uint8_t); ssize_t readip(struct iodesc *, void **, void **, time_t, uint8_t); ssize_t sendudp(struct iodesc *, void *, size_t); ssize_t readudp(struct iodesc *, void **, void **, time_t); ssize_t sendrecv(struct iodesc *, ssize_t (*)(struct iodesc *, void *, size_t), void *, size_t, ssize_t (*)(struct iodesc *, void **, void **, time_t, void *), void **, void **, void *); /* bootp/DHCP */ void bootp(int); /* Utilities: */ char *ether_sprintf(u_char *); int in_cksum(void *, int); char *inet_ntoa(struct in_addr); char *intoa(n_long); /* similar to inet_ntoa */ n_long inet_addr(char *); #endif /* ! _STAND_NET_H */ diff --git a/stand/libsa/netif.c b/stand/libsa/netif.c index d255cc663d5a..2d32ccd9de7e 100644 --- a/stand/libsa/netif.c +++ b/stand/libsa/netif.c @@ -1,316 +1,388 @@ /* $NetBSD: netif.c,v 1.10 1997/09/06 13:57:14 drochner Exp $ */ /* * Copyright (c) 1993 Adam Glass * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Adam Glass. * 4. The name of the Author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include "stand.h" #include "net.h" #include "netif.h" -struct iodesc sockets[SOPEN_MAX]; +typedef TAILQ_HEAD(socket_list, iodesc) socket_list_t; + +/* + * Open socket list. The current implementation and assumption is, + * we only remove entries from tail and we only add new entries to tail. + * This decision is to keep iodesc id management simple - we get list + * entries ordered by continiously growing io_id field. + * If we do have multiple sockets open and we do close socket not from tail, + * this entry will be marked unused. netif_open() will reuse unused entry, or + * netif_close() will free all unused tail entries. + */ +static socket_list_t sockets = TAILQ_HEAD_INITIALIZER(sockets); + #ifdef NETIF_DEBUG int netif_debug = 0; #endif /* * netif_init: * * initialize the generic network interface layer */ void netif_init(void) { struct netif_driver *drv; int d, i; - + #ifdef NETIF_DEBUG if (netif_debug) printf("netif_init: called\n"); #endif for (d = 0; netif_drivers[d]; d++) { drv = netif_drivers[d]; for (i = 0; i < drv->netif_nifs; i++) drv->netif_ifs[i].dif_used = 0; } } int netif_match(struct netif *nif, void *machdep_hint) { struct netif_driver *drv = nif->nif_driver; #if NETIF_DEBUG if (netif_debug) printf("%s%d: netif_match (%d)\n", drv->netif_bname, nif->nif_unit, nif->nif_sel); #endif return drv->netif_match(nif, machdep_hint); } struct netif * netif_select(void *machdep_hint) { int d, u, unit_done, s; struct netif_driver *drv; struct netif cur_if; static struct netif best_if; int best_val; int val; best_val = 0; best_if.nif_driver = NULL; for (d = 0; netif_drivers[d] != NULL; d++) { cur_if.nif_driver = netif_drivers[d]; drv = cur_if.nif_driver; for (u = 0; u < drv->netif_nifs; u++) { cur_if.nif_unit = u; unit_done = 0; - + #ifdef NETIF_DEBUG if (netif_debug) printf("\t%s%d:", drv->netif_bname, cur_if.nif_unit); #endif for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) { cur_if.nif_sel = s; if (drv->netif_ifs[u].dif_used & (1 << s)) { #ifdef NETIF_DEBUG if (netif_debug) printf(" [%d used]", s); #endif continue; } val = netif_match(&cur_if, machdep_hint); #ifdef NETIF_DEBUG if (netif_debug) printf(" [%d -> %d]", s, val); #endif if (val > best_val) { best_val = val; best_if = cur_if; } } #ifdef NETIF_DEBUG if (netif_debug) printf("\n"); #endif } } if (best_if.nif_driver == NULL) return NULL; best_if.nif_driver-> netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel); #ifdef NETIF_DEBUG if (netif_debug) printf("netif_select: %s%d(%d) wins\n", best_if.nif_driver->netif_bname, best_if.nif_unit, best_if.nif_sel); #endif return &best_if; } int netif_probe(struct netif *nif, void *machdep_hint) { struct netif_driver *drv = nif->nif_driver; #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit); #endif return drv->netif_probe(nif, machdep_hint); } void netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint) { struct netif_driver *drv = nif->nif_driver; #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit); #endif - desc->io_netif = nif; + desc->io_netif = nif; #ifdef PARANOID if (drv->netif_init == NULL) panic("%s%d: no netif_init support", drv->netif_bname, nif->nif_unit); #endif drv->netif_init(desc, machdep_hint); - bzero(drv->netif_ifs[nif->nif_unit].dif_stats, + bzero(drv->netif_ifs[nif->nif_unit].dif_stats, sizeof(struct netif_stats)); } void netif_detach(struct netif *nif) { struct netif_driver *drv = nif->nif_driver; #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit); #endif #ifdef PARANOID if (drv->netif_end == NULL) panic("%s%d: no netif_end support", drv->netif_bname, nif->nif_unit); #endif drv->netif_end(nif); } ssize_t netif_get(struct iodesc *desc, void **pkt, time_t timo) { #ifdef NETIF_DEBUG struct netif *nif = desc->io_netif; #endif struct netif_driver *drv = desc->io_netif->nif_driver; ssize_t rv; #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit); #endif #ifdef PARANOID if (drv->netif_get == NULL) panic("%s%d: no netif_get support", drv->netif_bname, nif->nif_unit); #endif rv = drv->netif_get(desc, pkt, timo); #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_get returning %d\n", drv->netif_bname, nif->nif_unit, (int)rv); #endif return (rv); } ssize_t netif_put(struct iodesc *desc, void *pkt, size_t len) { #ifdef NETIF_DEBUG struct netif *nif = desc->io_netif; #endif struct netif_driver *drv = desc->io_netif->nif_driver; ssize_t rv; #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit); #endif #ifdef PARANOID if (drv->netif_put == NULL) panic("%s%d: no netif_put support", drv->netif_bname, nif->nif_unit); #endif rv = drv->netif_put(desc, pkt, len); #ifdef NETIF_DEBUG if (netif_debug) printf("%s%d: netif_put returning %d\n", drv->netif_bname, nif->nif_unit, (int)rv); #endif return (rv); } +/* + * socktodesc_impl: + * + * Walk socket list and return pointer to iodesc structure. + * if id is < 0, return first unused iodesc. + */ +static struct iodesc * +socktodesc_impl(int socket) +{ + struct iodesc *s; + + TAILQ_FOREACH(s, &sockets, io_link) { + /* search by socket id */ + if (socket >= 0) { + if (s->io_id == socket) + break; + continue; + } + /* search for first unused entry */ + if (s->io_netif == NULL) + break; + } + return (s); +} + struct iodesc * socktodesc(int sock) { - if (sock >= SOPEN_MAX) { + struct iodesc *desc; + + if (sock < 0) + desc = NULL; + else + desc = socktodesc_impl(sock); + + if (desc == NULL) errno = EBADF; - return (NULL); - } - return (&sockets[sock]); + + return (desc); } int netif_open(void *machdep_hint) { - int fd; struct iodesc *s; struct netif *nif; - + /* find a free socket */ - for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++) - if (s->io_netif == (struct netif *)0) - goto fnd; - errno = EMFILE; - return (-1); - -fnd: - bzero(s, sizeof(*s)); + s = socktodesc_impl(-1); + if (s == NULL) { + struct iodesc *last; + + s = calloc(1, sizeof (*s)); + if (s == NULL) + return (-1); + + last = TAILQ_LAST(&sockets, socket_list); + if (last != NULL) + s->io_id = last->io_id + 1; + TAILQ_INSERT_TAIL(&sockets, s, io_link); + } + netif_init(); nif = netif_select(machdep_hint); - if (!nif) + if (!nif) panic("netboot: no interfaces left untried"); if (netif_probe(nif, machdep_hint)) { printf("netboot: couldn't probe %s%d\n", nif->nif_driver->netif_bname, nif->nif_unit); errno = EINVAL; return (-1); } netif_attach(nif, s, machdep_hint); - return (fd); + return (s->io_id); } int netif_close(int sock) { - if (sock >= SOPEN_MAX) { - errno = EBADF; + struct iodesc *s, *last; + int err; + + err = 0; + s = socktodesc_impl(sock); + if (s == NULL || sock < 0) { + err = EBADF; + return (-1); + } + netif_detach(s->io_netif); + bzero(&s->destip, sizeof (s->destip)); + bzero(&s->myip, sizeof (s->myip)); + s->destport = 0; + s->myport = 0; + s->xid = 0; + bzero(s->myea, sizeof (s->myea)); + s->io_netif = NULL; + + /* free unused entries from tail. */ + TAILQ_FOREACH_REVERSE_SAFE(last, &sockets, socket_list, io_link, s) { + if (last->io_netif != NULL) + break; + TAILQ_REMOVE(&sockets, last, io_link); + free(last); + } + + if (err) { + errno = err; return (-1); } - netif_detach(sockets[sock].io_netif); - sockets[sock].io_netif = (struct netif *)0; return (0); } diff --git a/stand/libsa/open.c b/stand/libsa/open.c index 9590508b0015..c62e48f0e1d8 100644 --- a/stand/libsa/open.c +++ b/stand/libsa/open.c @@ -1,163 +1,211 @@ /* $NetBSD: open.c,v 1.16 1997/01/28 09:41:03 pk Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)open.c 8.1 (Berkeley) 6/11/93 * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include "stand.h" struct fs_ops *exclusive_file_system; -struct open_file files[SOPEN_MAX]; +/* + * Open file list. The current implementation and assumption is, + * we only remove entries from tail and we only add new entries to tail. + * This decision is to keep file id management simple - we get list + * entries ordered by continiously growing f_id field. + * If we do have multiple files open and we do close file not from tail, + * this entry will be marked unused. open() will reuse unused entry, or + * close will free all unused tail entries. + * + * Only case we expect open file list to grow long, is with zfs pools with + * many disks. + */ +file_list_t files = TAILQ_HEAD_INITIALIZER(files); + +/* + * Walk file list and return pointer to open_file structure. + * if fd is < 0, return first unused open_file. + */ +struct open_file * +fd2open_file(int fd) +{ + struct open_file *f; + + TAILQ_FOREACH(f, &files, f_link) { + if (fd >= 0) { + if (f->f_id == fd) + break; + continue; + } + + if (f->f_flags == 0) + break; + } + return (f); +} static int -o_gethandle(void) +o_gethandle(struct open_file **ptr) { - int fd; + struct open_file *f, *last; - for (fd = 0; fd < SOPEN_MAX; fd++) - if (files[fd].f_flags == 0) - return (fd); - return (-1); + /* Pick up unused entry */ + f = fd2open_file(-1); + if (f != NULL) { + *ptr = f; + return (f->f_id); + } + + /* Add new entry */ + f = calloc(1, sizeof (*f)); + if (f == NULL) + return (-1); + + last = TAILQ_LAST(&files, file_list); + if (last != NULL) + f->f_id = last->f_id + 1; + TAILQ_INSERT_TAIL(&files, f, f_link); + + *ptr = f; + return (f->f_id); } static void o_rainit(struct open_file *f) { f->f_rabuf = malloc(SOPEN_RASIZE); f->f_ralen = 0; f->f_raoffset = 0; } int open(const char *fname, int mode) { struct fs_ops *fs; struct open_file *f; int fd, i, error, besterror; const char *file; TSENTER(); - if ((fd = o_gethandle()) == -1) { + if ((fd = o_gethandle(&f)) == -1) { errno = EMFILE; return (-1); } - f = &files[fd]; f->f_flags = mode + 1; f->f_dev = NULL; f->f_ops = NULL; f->f_offset = 0; f->f_devdata = NULL; file = NULL; if (exclusive_file_system != NULL) { fs = exclusive_file_system; error = (fs->fo_open)(fname, f); if (error == 0) goto ok; goto err; } error = devopen(f, fname, &file); if (error || (((f->f_flags & F_NODEV) == 0) && f->f_dev == NULL)) goto err; /* see if we opened a raw device; otherwise, 'file' is the file name. */ if (file == NULL || *file == '\0') { f->f_flags |= F_RAW; f->f_rabuf = NULL; TSEXIT(); return (fd); } /* pass file name to the different filesystem open routines */ besterror = ENOENT; for (i = 0; file_system[i] != NULL; i++) { fs = file_system[i]; error = (fs->fo_open)(file, f); if (error == 0) goto ok; if (error != EINVAL) besterror = error; } error = besterror; if ((f->f_flags & F_NODEV) == 0 && f->f_dev != NULL) f->f_dev->dv_close(f); if (error) devclose(f); err: f->f_flags = 0; errno = error; TSEXIT(); return (-1); ok: f->f_ops = fs; o_rainit(f); TSEXIT(); return (fd); } diff --git a/stand/libsa/read.c b/stand/libsa/read.c index 7ad75c387a5d..d079944bf5d0 100644 --- a/stand/libsa/read.c +++ b/stand/libsa/read.c @@ -1,141 +1,142 @@ /* $NetBSD: read.c,v 1.8 1997/01/22 00:38:12 cgd Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)read.c 8.1 (Berkeley) 6/11/93 * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include #include "stand.h" ssize_t read(int fd, void *dest, size_t bcount) { - struct open_file *f = &files[fd]; + struct open_file *f; size_t resid; TSENTER(); - if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) { + f = fd2open_file(fd); + if (f == NULL || !(f->f_flags & F_READ)) { errno = EBADF; return (-1); } if (f->f_flags & F_RAW) { twiddle(4); errno = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, btodb(f->f_offset), bcount, dest, &resid); if (errno) return (-1); f->f_offset += resid; TSEXIT(); return (resid); } /* * Optimise reads from regular files using a readahead buffer. * If the request can't be satisfied from the current buffer contents, * check to see if it should be bypassed, or refill the buffer and * complete the request. */ resid = bcount; for (;;) { size_t ccount, cresid; /* how much can we supply? */ ccount = imin(f->f_ralen, resid); if (ccount > 0) { bcopy(f->f_rabuf + f->f_raoffset, dest, ccount); f->f_raoffset += ccount; f->f_ralen -= ccount; resid -= ccount; if (resid == 0) { TSEXIT(); return (bcount); } dest = (char *)dest + ccount; } /* will filling the readahead buffer again not help? */ if (f->f_rabuf == NULL || resid >= SOPEN_RASIZE) { /* * bypass the rest of the request and leave the * buffer empty */ errno = (f->f_ops->fo_read)(f, dest, resid, &cresid); if (errno != 0) return (-1); TSEXIT(); return (bcount - cresid); } /* fetch more data */ errno = (f->f_ops->fo_read)(f, f->f_rabuf, SOPEN_RASIZE, &cresid); if (errno != 0) return (-1); f->f_raoffset = 0; f->f_ralen = SOPEN_RASIZE - cresid; /* no more data, return what we had */ if (f->f_ralen == 0) { TSEXIT(); return (bcount - resid); } } } diff --git a/stand/libsa/readdir.c b/stand/libsa/readdir.c index e49d93d15ed6..7757647e11e8 100644 --- a/stand/libsa/readdir.c +++ b/stand/libsa/readdir.c @@ -1,51 +1,52 @@ /*- * Copyright (c) 1999,2000 Jonathan Lemon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include "stand.h" struct dirent * readdirfd(int fd) { static struct dirent dir; /* XXX not thread safe */ - struct open_file *f = &files[fd]; + struct open_file *f; - if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) { + f = fd2open_file(fd); + if (f == NULL || !(f->f_flags & F_READ)) { errno = EBADF; return (NULL); } if (f->f_flags & F_RAW) { errno = EIO; return (NULL); } errno = (f->f_ops->fo_readdir)(f, &dir); if (errno) return (NULL); return (&dir); } diff --git a/stand/libsa/stand.h b/stand/libsa/stand.h index eb95afe4b169..535fee31d586 100644 --- a/stand/libsa/stand.h +++ b/stand/libsa/stand.h @@ -1,485 +1,489 @@ /* * Copyright (c) 1998 Michael Smith. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * From $NetBSD: stand.h,v 1.22 1997/06/26 19:17:40 drochner Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)stand.h 8.1 (Berkeley) 6/11/93 */ #ifndef STAND_H #define STAND_H #include #include #include #include +#include /* this header intentionally exports NULL from */ #include #define strcoll(a, b) strcmp((a), (b)) #define CHK(fmt, args...) printf("%s(%d): " fmt "\n", __func__, __LINE__ , ##args) #define PCHK(fmt, args...) {printf("%s(%d): " fmt "\n", __func__, __LINE__ , ##args); getchar();} #include /* special stand error codes */ #define EADAPT (ELAST+1) /* bad adaptor */ #define ECTLR (ELAST+2) /* bad controller */ #define EUNIT (ELAST+3) /* bad unit */ #define ESLICE (ELAST+4) /* bad slice */ #define EPART (ELAST+5) /* bad partition */ #define ERDLAB (ELAST+6) /* can't read disk label */ #define EUNLAB (ELAST+7) /* unlabeled disk */ #define EOFFSET (ELAST+8) /* relative seek not supported */ #define ESALAST (ELAST+8) /* */ /* Partial signal emulation for sig_atomic_t */ #include struct open_file; /* * This structure is used to define file system operations in a file system * independent way. * * XXX note that filesystem providers should export a pointer to their fs_ops * struct, so that consumers can reference this and thus include the * filesystems that they require. */ struct fs_ops { const char *fs_name; int (*fo_open)(const char *path, struct open_file *f); int (*fo_close)(struct open_file *f); int (*fo_read)(struct open_file *f, void *buf, size_t size, size_t *resid); int (*fo_write)(struct open_file *f, const void *buf, size_t size, size_t *resid); off_t (*fo_seek)(struct open_file *f, off_t offset, int where); int (*fo_stat)(struct open_file *f, struct stat *sb); int (*fo_readdir)(struct open_file *f, struct dirent *d); }; /* * libstand-supplied filesystems */ extern struct fs_ops ufs_fsops; extern struct fs_ops tftp_fsops; extern struct fs_ops nfs_fsops; extern struct fs_ops cd9660_fsops; extern struct fs_ops gzipfs_fsops; extern struct fs_ops bzipfs_fsops; extern struct fs_ops dosfs_fsops; extern struct fs_ops ext2fs_fsops; extern struct fs_ops splitfs_fsops; extern struct fs_ops pkgfs_fsops; extern struct fs_ops efihttp_fsops; /* where values for lseek(2) */ #define SEEK_SET 0 /* set file offset to offset */ #define SEEK_CUR 1 /* set file offset to current plus offset */ #define SEEK_END 2 /* set file offset to EOF plus offset */ /* * Device switch */ struct devsw { const char dv_name[8]; int dv_type; /* opaque type constant, arch-dependant */ #define DEVT_NONE 0 #define DEVT_DISK 1 #define DEVT_NET 2 #define DEVT_CD 3 #define DEVT_ZFS 4 #define DEVT_FD 5 int (*dv_init)(void); /* early probe call */ int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize); int (*dv_open)(struct open_file *f, ...); int (*dv_close)(struct open_file *f); int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data); int (*dv_print)(int verbose); /* print device information */ void (*dv_cleanup)(void); }; /* * libstand-supplied device switch */ extern struct devsw netdev; extern int errno; /* * Generic device specifier; architecture-dependent * versions may be larger, but should be allowed to * overlap. */ struct devdesc { struct devsw *d_dev; int d_unit; void *d_opendata; }; struct open_file { int f_flags; /* see F_* below */ struct devsw *f_dev; /* pointer to device operations */ void *f_devdata; /* device specific data */ struct fs_ops *f_ops; /* pointer to file system operations */ void *f_fsdata; /* file system specific data */ off_t f_offset; /* current file offset */ char *f_rabuf; /* readahead buffer pointer */ size_t f_ralen; /* valid data in readahead buffer */ off_t f_raoffset; /* consumer offset in readahead buffer */ + int f_id; /* file number */ + TAILQ_ENTRY(open_file) f_link; /* next entry */ #define SOPEN_RASIZE 512 }; -#define SOPEN_MAX 64 -extern struct open_file files[]; +typedef TAILQ_HEAD(file_list, open_file) file_list_t; +extern file_list_t files; +extern struct open_file *fd2open_file(int); /* f_flags values */ #define F_READ 0x0001 /* file opened for reading */ #define F_WRITE 0x0002 /* file opened for writing */ #define F_RAW 0x0004 /* raw device open - no file system */ #define F_NODEV 0x0008 /* network open - no device */ #define F_MASK 0xFFFF /* Mode modifier for strategy() */ #define F_NORA (0x01 << 16) /* Disable Read-Ahead */ #define isascii(c) (((c) & ~0x7F) == 0) static __inline int isupper(int c) { return c >= 'A' && c <= 'Z'; } static __inline int islower(int c) { return c >= 'a' && c <= 'z'; } static __inline int isspace(int c) { return c == ' ' || (c >= 0x9 && c <= 0xd); } static __inline int isdigit(int c) { return c >= '0' && c <= '9'; } static __inline int isxdigit(int c) { return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); } static __inline int isalpha(int c) { return isupper(c) || islower(c); } static __inline int isalnum(int c) { return isalpha(c) || isdigit(c); } static __inline int iscntrl(int c) { return (c >= 0 && c < ' ') || c == 127; } static __inline int isgraph(int c) { return c >= '!' && c <= '~'; } static __inline int ispunct(int c) { return (c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~'); } static __inline int toupper(int c) { return islower(c) ? c - 'a' + 'A' : c; } static __inline int tolower(int c) { return isupper(c) ? c - 'A' + 'a' : c; } /* sbrk emulation */ extern void setheap(void *base, void *top); extern char *sbrk(int incr); extern int printf(const char *fmt, ...) __printflike(1, 2); extern int asprintf(char **buf, const char *cfmt, ...) __printflike(2, 3); extern int sprintf(char *buf, const char *cfmt, ...) __printflike(2, 3); extern int snprintf(char *buf, size_t size, const char *cfmt, ...) __printflike(3, 4); extern int vprintf(const char *fmt, __va_list); extern int vsprintf(char *buf, const char *cfmt, __va_list); extern int vsnprintf(char *buf, size_t size, const char *cfmt, __va_list); extern void twiddle(u_int callerdiv); extern void twiddle_divisor(u_int globaldiv); extern void ngets(char *, int); #define gets(x) ngets((x), 0) extern int fgetstr(char *buf, int size, int fd); extern int open(const char *, int); #define O_RDONLY 0x0 #define O_WRONLY 0x1 #define O_RDWR 0x2 #define O_ACCMODE 0x3 /* NOT IMPLEMENTED */ #define O_CREAT 0x0200 /* create if nonexistent */ #define O_TRUNC 0x0400 /* truncate to zero length */ extern int close(int); extern void closeall(void); extern ssize_t read(int, void *, size_t); extern ssize_t write(int, const void *, size_t); extern struct dirent *readdirfd(int); extern void srandom(unsigned int); extern long random(void); /* imports from stdlib, locally modified */ extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt, optreset; extern int getopt(int, char * const [], const char *); /* pager.c */ extern void pager_open(void); extern void pager_close(void); extern int pager_output(const char *lines); extern int pager_file(const char *fname); /* No signal state to preserve */ #define setjmp _setjmp #define longjmp _longjmp /* environment.c */ #define EV_DYNAMIC (1<<0) /* value was dynamically allocated, free if changed/unset */ #define EV_VOLATILE (1<<1) /* value is volatile, make a copy of it */ #define EV_NOHOOK (1<<2) /* don't call hook when setting */ struct env_var; typedef char *(ev_format_t)(struct env_var *ev); typedef int (ev_sethook_t)(struct env_var *ev, int flags, const void *value); typedef int (ev_unsethook_t)(struct env_var *ev); struct env_var { char *ev_name; int ev_flags; void *ev_value; ev_sethook_t *ev_sethook; ev_unsethook_t *ev_unsethook; struct env_var *ev_next, *ev_prev; }; extern struct env_var *environ; extern struct env_var *env_getenv(const char *name); extern int env_setenv(const char *name, int flags, const void *value, ev_sethook_t sethook, ev_unsethook_t unsethook); extern void env_discard(struct env_var *); extern char *getenv(const char *name); extern int setenv(const char *name, const char *value, int overwrite); extern int putenv(char *string); extern int unsetenv(const char *name); extern ev_sethook_t env_noset; /* refuse set operation */ extern ev_unsethook_t env_nounset; /* refuse unset operation */ /* stdlib.h routines */ extern int abs(int a); extern void abort(void) __dead2; extern long strtol(const char * __restrict, char ** __restrict, int); extern long long strtoll(const char * __restrict, char ** __restrict, int); extern unsigned long strtoul(const char * __restrict, char ** __restrict, int); extern unsigned long long strtoull(const char * __restrict, char ** __restrict, int); /* BCD conversions (undocumented) */ extern u_char const bcd2bin_data[]; extern u_char const bin2bcd_data[]; extern char const hex2ascii_data[]; #define bcd2bin(bcd) (bcd2bin_data[bcd]) #define bin2bcd(bin) (bin2bcd_data[bin]) #define hex2ascii(hex) (hex2ascii_data[hex]) #define validbcd(bcd) (bcd == 0 || (bcd > 0 && bcd <= 0x99 && bcd2bin_data[bcd] != 0)) /* min/max (undocumented) */ static __inline int imax(int a, int b) { return (a > b ? a : b); } static __inline int imin(int a, int b) { return (a < b ? a : b); } static __inline long lmax(long a, long b) { return (a > b ? a : b); } static __inline long lmin(long a, long b) { return (a < b ? a : b); } static __inline u_int max(u_int a, u_int b) { return (a > b ? a : b); } static __inline u_int min(u_int a, u_int b) { return (a < b ? a : b); } static __inline quad_t qmax(quad_t a, quad_t b) { return (a > b ? a : b); } static __inline quad_t qmin(quad_t a, quad_t b) { return (a < b ? a : b); } static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); } static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); } /* null functions for device/filesystem switches (undocumented) */ extern int nodev(void); extern int noioctl(struct open_file *, u_long, void *); extern void nullsys(void); extern int null_open(const char *path, struct open_file *f); extern int null_close(struct open_file *f); extern int null_read(struct open_file *f, void *buf, size_t size, size_t *resid); extern int null_write(struct open_file *f, const void *buf, size_t size, size_t *resid); extern off_t null_seek(struct open_file *f, off_t offset, int where); extern int null_stat(struct open_file *f, struct stat *sb); extern int null_readdir(struct open_file *f, struct dirent *d); /* * Machine dependent functions and data, must be provided or stubbed by * the consumer */ extern void exit(int) __dead2; extern int getchar(void); extern int ischar(void); extern void putchar(int); extern int devopen(struct open_file *, const char *, const char **); extern int devclose(struct open_file *f); extern void panic(const char *, ...) __dead2 __printflike(1, 2); extern void panic_action(void) __weak_symbol __dead2; extern time_t getsecs(void); extern struct fs_ops *file_system[]; extern struct fs_ops *exclusive_file_system; extern struct devsw *devsw[]; /* * Time routines */ time_t time(time_t *); /* * Expose byteorder(3) functions. */ #ifndef _BYTEORDER_PROTOTYPED #define _BYTEORDER_PROTOTYPED extern uint32_t htonl(uint32_t); extern uint16_t htons(uint16_t); extern uint32_t ntohl(uint32_t); extern uint16_t ntohs(uint16_t); #endif #ifndef _BYTEORDER_FUNC_DEFINED #define _BYTEORDER_FUNC_DEFINED #define htonl(x) __htonl(x) #define htons(x) __htons(x) #define ntohl(x) __ntohl(x) #define ntohs(x) __ntohs(x) #endif void *Malloc(size_t, const char *, int); void *Memalign(size_t, size_t, const char *, int); void *Calloc(size_t, size_t, const char *, int); void *Realloc(void *, size_t, const char *, int); void *Reallocf(void *, size_t, const char *, int); void Free(void *, const char *, int); extern void mallocstats(void); const char *x86_hypervisor(void); #ifdef USER_MALLOC extern void *malloc(size_t); extern void *memalign(size_t, size_t); extern void *calloc(size_t, size_t); extern void free(void *); extern void *realloc(void *, size_t); extern void *reallocf(void *, size_t); #elif defined(DEBUG_MALLOC) #define malloc(x) Malloc(x, __FILE__, __LINE__) #define memalign(x, y) Memalign(x, y, __FILE__, __LINE__) #define calloc(x, y) Calloc(x, y, __FILE__, __LINE__) #define free(x) Free(x, __FILE__, __LINE__) #define realloc(x, y) Realloc(x, y, __FILE__, __LINE__) #define reallocf(x, y) Reallocf(x, y, __FILE__, __LINE__) #else #define malloc(x) Malloc(x, NULL, 0) #define memalign(x, y) Memalign(x, y, NULL, 0) #define calloc(x, y) Calloc(x, y, NULL, 0) #define free(x) Free(x, NULL, 0) #define realloc(x, y) Realloc(x, y, NULL, 0) #define reallocf(x, y) Reallocf(x, y, NULL, 0) #endif /* * va <-> pa routines. MD code must supply. */ caddr_t ptov(uintptr_t); /* hexdump.c */ void hexdump(caddr_t region, size_t len); /* tslog.c */ #define TSRAW(a, b, c) tslog(a, b, c) #define TSENTER() TSRAW("ENTER", __func__, NULL) #define TSEXIT() TSRAW("EXIT", __func__, NULL) #define TSLINE() TSRAW("EVENT", __FILE__, __XSTRING(__LINE__)) void tslog(const char *, const char *, const char *); void tslog_setbuf(void * buf, size_t len); void tslog_getbuf(void ** buf, size_t * len); #endif /* STAND_H */ diff --git a/stand/libsa/write.c b/stand/libsa/write.c index 7d054e005cda..db82d7eaf4f6 100644 --- a/stand/libsa/write.c +++ b/stand/libsa/write.c @@ -1,93 +1,94 @@ /* $NetBSD: write.c,v 1.7 1996/06/21 20:29:30 pk Exp $ */ /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * The Mach Operating System project at Carnegie-Mellon University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)write.c 8.1 (Berkeley) 6/11/93 * * * Copyright (c) 1989, 1990, 1991 Carnegie Mellon University * All Rights Reserved. * * Author: Alessandro Forin * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. */ #include __FBSDID("$FreeBSD$"); #include #include "stand.h" ssize_t write(int fd, const void *dest, size_t bcount) { - struct open_file *f = &files[fd]; + struct open_file *f; size_t resid; - if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_WRITE)) { + f = fd2open_file(fd); + if (f == NULL || !(f->f_flags & F_WRITE)) { errno = EBADF; return (-1); } if (f->f_flags & F_RAW) { twiddle(4); errno = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE, btodb(f->f_offset), bcount, __DECONST(void *, dest), &resid); if (errno) return (-1); f->f_offset += resid; return (resid); } resid = bcount; if ((errno = (f->f_ops->fo_write)(f, dest, bcount, &resid))) return (-1); return (bcount - resid); }