This is libstand; a support library for standalone executables (eg. bootstrap

modules).
Obtained from: NetBSD, with some architectural changes and many additions.
This commit is contained in:
Mike Smith 1998-08-20 08:19:55 +00:00
parent 5879dcdb05
commit 6b4f575cb1
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MSMITH/; revision=38451
60 changed files with 11408 additions and 0 deletions

116
lib/libstand/Makefile Normal file
View File

@ -0,0 +1,116 @@
# $Id$
#
# Originally from $NetBSD: Makefile,v 1.21 1997/10/26 22:08:38 lukem Exp $
#
# Notes:
# - We don't use the libc strerror/sys_errlist because the string table is
# quite large.
#
LIB= stand
NOPROFILE= YES
NOPIC= YES
# Mostly OK, some of the libc imports are a bit noisy
CFLAGS+= -Wall
# i386 apps are loaded by an a.out only loader
.if ${MACHINE_ARCH} == "i386"
OBJFORMAT= aout
.endif
.if ${MACHINE_ARCH} == "alpha"
CFLAGS+= -mno-fp-regs
.endif
# standalone components and stuff we have modified locally
SRCS+= __main.c alloc.c bcd.c bswap.c environment.c getopt.c gets.c \
globals.c pager.c printf.c strdup.c strerror.c strtol.c random.c \
twiddle.c
# string functions from libc
.PATH: ${.CURDIR}/../libc/string
.if ${MACHINE_ARCH} == "i386"
SRCS+= bcmp.c bcopy.c bzero.c ffs.c index.c memccpy.c memchr.c memcmp.c \
memcpy.c memmove.c memset.c rindex.c strcasecmp.c strcat.c strchr.c \
strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c \
strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
.endif
.if ${MACHINE_ARCH} == "alpha"
.PATH: ${.CURDIR}/../libc/alpha/string
SRCS+= bcmp.c bcopy.S bzero.S ffs.S index.c memccpy.c memchr.c memcmp.c \
memcpy.S memmove.S memset.c rindex.c strcasecmp.c strcat.c strchr.c \
strcmp.c strcpy.c strcspn.c strlen.c \
strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strsep.c \
strspn.c strstr.c strtok.c swab.c
.PATH: ${.CURDIR}/../libc/alpha/net
SRCS+= htons.S ntohs.S htonl.S ntohl.S
SRCS+= __divqu.S __divq.S __divlu.S __divl.S
SRCS+= __remqu.S __remq.S __remlu.S __reml.S
CLEANFILES+= __divqu.S __divq.S __divlu.S __divl.S
CLEANFILES+= __remqu.S __remq.S __remlu.S __reml.S
__divqu.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__divqu -DOP=div -DS=false -DWORDSIZE=64 \
${.ALLSRC} > ${.TARGET}
__divq.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__divq -DOP=div -DS=true -DWORDSIZE=64 \
${.ALLSRC} > ${.TARGET}
__divlu.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__divlu -DOP=div -DS=false -DWORDSIZE=32 \
${.ALLSRC} > ${.TARGET}
__divl.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__divl -DOP=div -DS=true -DWORDSIZE=32 \
${.ALLSRC} > ${.TARGET}
__remqu.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__remqu -DOP=rem -DS=false -DWORDSIZE=64 \
${.ALLSRC} > ${.TARGET}
__remq.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__remq -DOP=rem -DS=true -DWORDSIZE=64 \
${.ALLSRC} > ${.TARGET}
__remlu.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__remlu -DOP=rem -DS=false -DWORDSIZE=32 \
${.ALLSRC} > ${.TARGET}
__reml.S: ${.CURDIR}/../libc/alpha/gen/divrem.m4
m4 -DNAME=__reml -DOP=rem -DS=true -DWORDSIZE=32 \
${.ALLSRC} > ${.TARGET}
.endif
# network support from libc
.PATH: ${.CURDIR}/../libc/net
SRCS+= inet_ntoa.c inet_addr.c
# decompression functionality from libz
.PATH: ${.CURDIR}/../libz
CFLAGS+=-DHAVE_MEMCPY
SRCS+= adler32.c crc32.c infblock.c infcodes.c inffast.c inflate.c \
inftrees.c infutil.c zutil.c
# io routines
SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c \
fstat.c close.c lseek.c open.c read.c write.c
# network routines
SRCS+= arp.c ether.c in_cksum.c net.c netif.c rpc.c
# network info services:
SRCS+= bootp.c rarp.c bootparam.c
# boot filesystems
SRCS+= ufs.c nfs.c cd9660.c tftp.c zipfs.c
SRCS+= netif.c nfs.c
# needs "open directory" support
#SRCS+= dosfs.c
.include <bsd.lib.mk>

40
lib/libstand/__main.c Normal file
View File

@ -0,0 +1,40 @@
/* $NetBSD: __main.c,v 1.4 1996/03/14 18:52:03 christos Exp $ */
/*
* Copyright (c) 1993 Christopher G. Demetriou
* 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 Christopher G. Demetriou.
* 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 THE AUTHOR ``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 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 <sys/types.h>
void __main(void);
void
__main()
{
}

244
lib/libstand/alloc.c Normal file
View File

@ -0,0 +1,244 @@
/* $NetBSD: alloc.c,v 1.11 1997/09/17 16:24:00 drochner Exp $ */
/*
* Copyright (c) 1997 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1996
* Matthias Drochner. All rights reserved.
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)alloc.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.
*/
/*
* Dynamic memory allocator.
*
* Compile options:
*
* ALLOC_TRACE enable tracing of allocations/deallocations
* ALLOC_FIRST_FIT use a first-fit allocation algorithm, rather than
* the default best-fit algorithm.
*
* HEAP_LIMIT heap limit address (defaults to "no limit").
*
* HEAP_START start address of heap (defaults to '&end').
*
* DEBUG enable debugging sanity checks.
*/
#include <sys/param.h>
#include "stand.h"
/* Default to variable heap operation */
#define HEAP_VARIABLE
#define DEBUG
/*
* Each block actually has ALIGN(size_t) + ALIGN(size) bytes allocated
* to it, as follows:
*
* 0 ... (sizeof(size_t) - 1)
* allocated or unallocated: holds size of user-data part of block.
*
* sizeof(size_t) ... (ALIGN(sizeof(size_t)) - 1)
* allocated: unused
* unallocated: depends on packing of struct fl
*
* ALIGN(sizeof(size_t)) ... (ALIGN(sizeof(size_t)) + ALIGN(data size) - 1)
* allocated: user data
* unallocated: depends on packing of struct fl
*
* 'next' is only used when the block is unallocated (i.e. on the free list).
* However, note that ALIGN(sizeof(size_t)) + ALIGN(data size) must
* be at least 'sizeof(struct fl)', so that blocks can be used as structures
* when on the free list.
*/
struct fl {
size_t size;
struct fl *next;
} *freelist = (struct fl *)0;
#ifdef HEAP_VARIABLE
static char *top, *heapstart, *heaplimit;
void setheap(start, limit)
void *start, *limit;
{
heapstart = top = start;
heaplimit = limit;
}
#define HEAP_START heapstart
#define HEAP_LIMIT heaplimit
#else /* !HEAP_VARIABLE */
#ifndef HEAP_START
extern char end[];
#define HEAP_START end
#endif
static char *top = (char*)HEAP_START;
#endif /* HEAP_VARIABLE */
void *
malloc(size)
size_t size;
{
register struct fl **f = &freelist, **bestf = NULL;
size_t bestsize = 0xffffffff; /* greater than any real size */
char *help;
int failed;
#ifdef ALLOC_TRACE
printf("alloc(%u)", size);
#endif
#ifdef ALLOC_FIRST_FIT
while (*f != (struct fl *)0 && (*f)->size < size)
f = &((*f)->next);
bestf = f;
failed = (*bestf == (struct fl *)0);
#else
/* scan freelist */
while (*f) {
if ((*f)->size >= size) {
if ((*f)->size == size) /* exact match */
goto found;
if ((*f)->size < bestsize) {
/* keep best fit */
bestf = f;
bestsize = (*f)->size;
}
}
f = &((*f)->next);
}
/* no match in freelist if bestsize unchanged */
failed = (bestsize == 0xffffffff);
#endif
if (failed) { /* nothing found */
/*
* allocate from heap, keep chunk len in
* first word
*/
help = top;
/* make _sure_ the region can hold a struct fl. */
if (size < ALIGN(sizeof (struct fl *)))
size = ALIGN(sizeof (struct fl *));
top += ALIGN(sizeof(size_t)) + ALIGN(size);
#ifdef HEAP_LIMIT
if (top > (char*)HEAP_LIMIT)
panic("heap full (0x%lx+%u)", help, size);
#endif
*(size_t *)help = ALIGN(size);
#ifdef ALLOC_TRACE
printf("=%lx\n", (u_long)help + ALIGN(sizeof(size_t)));
getchar();
#endif
return(help + ALIGN(sizeof(size_t)));
}
/* we take the best fit */
f = bestf;
found:
/* remove from freelist */
help = (char*)*f;
*f = (*f)->next;
#ifdef ALLOC_TRACE
printf("=%lx (origsize %u)\n", (u_long)help + ALIGN(sizeof(size_t)),
*(size_t *)help);
getchar();
#endif
return(help + ALIGN(sizeof(size_t)));
}
void
free(ptr)
void *ptr;
{
register struct fl *f =
(struct fl *)((char*)ptr - ALIGN(sizeof(size_t)));
#ifdef ALLOC_TRACE
printf("free(%lx, %u) (origsize %u)\n", (u_long)ptr, size, f->size);
getchar();
#endif
#ifdef DEBUG
if (ptr < (void *)HEAP_START)
printf("free: %lx before start of heap.\n", (u_long)ptr);
#ifdef HEAP_LIMIT
if (ptr > (void *)HEAP_LIMIT)
printf("free: %lx beyond end of heap.\n", (u_long)ptr);
#endif
#endif /* DEBUG */
/* put into freelist */
f->next = freelist;
freelist = f;
}
/*
* Emulate sbrk(0) behaviour
*/
char *
sbrk(int junk)
{
return((char *)top);
}

310
lib/libstand/arp.c Normal file
View File

@ -0,0 +1,310 @@
/* $NetBSD: arp.c,v 1.18 1997/07/07 15:52:49 drochner Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL)
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <string.h>
#include "stand.h"
#include "net.h"
/* Cache stuff */
#define ARP_NUM 8 /* need at most 3 arp entries */
struct arp_list {
struct in_addr addr;
u_char ea[6];
} arp_list[ARP_NUM] = {
/* XXX - net order `INADDR_BROADCAST' must be a constant */
{ {0xffffffff}, BA }
};
int arp_num = 1;
/* Local forwards */
static ssize_t arpsend(struct iodesc *, void *, size_t);
static ssize_t arprecv(struct iodesc *, void *, size_t, time_t);
/* Broadcast an ARP packet, asking who has addr on interface d */
u_char *
arpwhohas(d, addr)
register struct iodesc *d;
struct in_addr addr;
{
register int i;
register struct ether_arp *ah;
register struct arp_list *al;
struct {
struct ether_header eh;
struct {
struct ether_arp arp;
u_char pad[18]; /* 60 - sizeof(...) */
} data;
} wbuf;
struct {
struct ether_header eh;
struct {
struct ether_arp arp;
u_char pad[24]; /* extra space */
} data;
} rbuf;
/* Try for cached answer first */
for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
if (addr.s_addr == al->addr.s_addr)
return (al->ea);
/* Don't overflow cache */
if (arp_num > ARP_NUM - 1) {
arp_num = 1; /* recycle */
printf("arpwhohas: overflowed arp_list!\n");
}
#ifdef ARP_DEBUG
if (debug)
printf("arpwhohas: send request for %s\n", inet_ntoa(addr));
#endif
bzero((char*)&wbuf.data, sizeof(wbuf.data));
ah = &wbuf.data.arp;
ah->arp_hrd = htons(ARPHRD_ETHER);
ah->arp_pro = htons(ETHERTYPE_IP);
ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */
ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */
ah->arp_op = htons(ARPOP_REQUEST);
MACPY(d->myea, ah->arp_sha);
bcopy(&d->myip, ah->arp_spa, sizeof(ah->arp_spa));
/* Leave zeros in arp_tha */
bcopy(&addr, ah->arp_tpa, sizeof(ah->arp_tpa));
/* Store ip address in cache (incomplete entry). */
al->addr = addr;
i = sendrecv(d,
arpsend, &wbuf.data, sizeof(wbuf.data),
arprecv, &rbuf.data, sizeof(rbuf.data));
if (i == -1) {
panic("arp: no response for %s\n",
inet_ntoa(addr));
}
/* Store ethernet address in cache */
ah = &rbuf.data.arp;
#ifdef ARP_DEBUG
if (debug) {
printf("arp: response from %s\n",
ether_sprintf(rbuf.eh.ether_shost));
printf("arp: cacheing %s --> %s\n",
inet_ntoa(addr), ether_sprintf(ah->arp_sha));
}
#endif
MACPY(ah->arp_sha, al->ea);
++arp_num;
return (al->ea);
}
static ssize_t
arpsend(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register size_t len;
{
#ifdef ARP_DEBUG
if (debug)
printf("arpsend: called\n");
#endif
return (sendether(d, pkt, len, bcea, ETHERTYPE_ARP));
}
/*
* Returns 0 if this is the packet we're waiting for
* else -1 (and errno == 0)
*/
static ssize_t
arprecv(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
{
register ssize_t n;
register struct ether_arp *ah;
u_int16_t etype; /* host order */
#ifdef ARP_DEBUG
if (debug)
printf("arprecv: ");
#endif
n = readether(d, pkt, len, tleft, &etype);
errno = 0; /* XXX */
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef ARP_DEBUG
if (debug)
printf("bad len=%d\n", n);
#endif
return (-1);
}
if (etype != ETHERTYPE_ARP) {
#ifdef ARP_DEBUG
if (debug)
printf("not arp type=%d\n", etype);
#endif
return (-1);
}
/* Ethernet address now checked in readether() */
ah = (struct ether_arp *)pkt;
if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
ah->arp_pro != htons(ETHERTYPE_IP) ||
ah->arp_hln != sizeof(ah->arp_sha) ||
ah->arp_pln != sizeof(ah->arp_spa) )
{
#ifdef ARP_DEBUG
if (debug)
printf("bad hrd/pro/hln/pln\n");
#endif
return (-1);
}
if (ah->arp_op == htons(ARPOP_REQUEST)) {
#ifdef ARP_DEBUG
if (debug)
printf("is request\n");
#endif
arp_reply(d, ah);
return (-1);
}
if (ah->arp_op != htons(ARPOP_REPLY)) {
#ifdef ARP_DEBUG
if (debug)
printf("not ARP reply\n");
#endif
return (-1);
}
/* Is the reply from the source we want? */
if (bcmp(&arp_list[arp_num].addr,
ah->arp_spa, sizeof(ah->arp_spa)))
{
#ifdef ARP_DEBUG
if (debug)
printf("unwanted address\n");
#endif
return (-1);
}
/* We don't care who the reply was sent to. */
/* We have our answer. */
#ifdef ARP_DEBUG
if (debug)
printf("got it\n");
#endif
return (n);
}
/*
* Convert an ARP request into a reply and send it.
* Notes: Re-uses buffer. Pad to length = 46.
*/
void
arp_reply(d, pkt)
register struct iodesc *d;
register void *pkt; /* the request */
{
struct ether_arp *arp = pkt;
if (arp->arp_hrd != htons(ARPHRD_ETHER) ||
arp->arp_pro != htons(ETHERTYPE_IP) ||
arp->arp_hln != sizeof(arp->arp_sha) ||
arp->arp_pln != sizeof(arp->arp_spa) )
{
#ifdef ARP_DEBUG
if (debug)
printf("arp_reply: bad hrd/pro/hln/pln\n");
#endif
return;
}
if (arp->arp_op != htons(ARPOP_REQUEST)) {
#ifdef ARP_DEBUG
if (debug)
printf("arp_reply: not request!\n");
#endif
return;
}
/* If we are not the target, ignore the request. */
if (bcmp(arp->arp_tpa, &d->myip, sizeof(arp->arp_tpa)))
return;
#ifdef ARP_DEBUG
if (debug) {
printf("arp_reply: to %s\n", ether_sprintf(arp->arp_sha));
}
#endif
arp->arp_op = htons(ARPOP_REPLY);
/* source becomes target */
bcopy(arp->arp_sha, arp->arp_tha, sizeof(arp->arp_tha));
bcopy(arp->arp_spa, arp->arp_tpa, sizeof(arp->arp_tpa));
/* here becomes source */
bcopy(d->myea, arp->arp_sha, sizeof(arp->arp_sha));
bcopy(&d->myip, arp->arp_spa, sizeof(arp->arp_spa));
/*
* No need to get fancy here. If the send fails, the
* requestor will just ask again.
*/
(void) sendether(d, pkt, sizeof(*arp) + 18,
arp->arp_tha, ETHERTYPE_ARP);
}

35
lib/libstand/bcd.c Normal file
View File

@ -0,0 +1,35 @@
/*
* Some data-tables that are often used.
* Cannot be copyrighted.
*/
#include <sys/libkern.h>
u_char const bcd2bin_data[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0, 0, 0, 0, 0, 0,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, 0, 0, 0, 0,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 0, 0, 0, 0, 0, 0,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, 0, 0, 0, 0, 0,
70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 0, 0, 0, 0, 0,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 0, 0, 0, 0, 0, 0,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99
};
u_char const bin2bcd_data[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
};
/* This is actually used with radix [2..36] */
char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";

396
lib/libstand/bootp.c Normal file
View File

@ -0,0 +1,396 @@
/* $NetBSD: bootp.c,v 1.14 1998/02/16 11:10:54 drochner Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp (LBL)
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <string.h>
#define BOOTP_DEBUGxx
#define SUPPORT_DHCP
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "bootp.h"
struct in_addr servip;
static n_long nmask, smask;
static time_t bot;
static char vm_rfc1048[4] = VM_RFC1048;
#ifdef BOOTP_VEND_CMU
static char vm_cmu[4] = VM_CMU;
#endif
/* Local forwards */
static ssize_t bootpsend(struct iodesc *, void *, size_t);
static ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
static int vend_rfc1048(u_char *, u_int);
#ifdef BOOTP_VEND_CMU
static void vend_cmu(u_char *);
#endif
#ifdef SUPPORT_DHCP
static char expected_dhcpmsgtype = -1, dhcp_ok;
struct in_addr dhcp_serverip;
#endif
/* Fetch required bootp infomation */
void
bootp(sock)
int sock;
{
struct iodesc *d;
register struct bootp *bp;
struct {
u_char header[HEADER_SIZE];
struct bootp wbootp;
} wbuf;
struct {
u_char header[HEADER_SIZE];
struct bootp rbootp;
} rbuf;
#ifdef BOOTP_DEBUG
if (debug)
printf("bootp: socket=%d\n", sock);
#endif
if (!bot)
bot = getsecs();
if (!(d = socktodesc(sock))) {
printf("bootp: bad socket. %d\n", sock);
return;
}
#ifdef BOOTP_DEBUG
if (debug)
printf("bootp: d=%lx\n", (long)d);
#endif
bp = &wbuf.wbootp;
bzero(bp, sizeof(*bp));
bp->bp_op = BOOTREQUEST;
bp->bp_htype = 1; /* 10Mb Ethernet (48 bits) */
bp->bp_hlen = 6;
bp->bp_xid = htonl(d->xid);
MACPY(d->myea, bp->bp_chaddr);
strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file));
bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));
#ifdef SUPPORT_DHCP
bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
bp->bp_vend[5] = 1;
bp->bp_vend[6] = DHCPDISCOVER;
bp->bp_vend[7] = TAG_END;
#else
bp->bp_vend[4] = TAG_END;
#endif
d->myip.s_addr = INADDR_ANY;
d->myport = htons(IPPORT_BOOTPC);
d->destip.s_addr = INADDR_BROADCAST;
d->destport = htons(IPPORT_BOOTPS);
#ifdef SUPPORT_DHCP
expected_dhcpmsgtype = DHCPOFFER;
dhcp_ok = 0;
#endif
if(sendrecv(d,
bootpsend, bp, sizeof(*bp),
bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
== -1) {
printf("bootp: no reply\n");
return;
}
#ifdef SUPPORT_DHCP
if(dhcp_ok) {
u_int32_t leasetime;
bp->bp_vend[6] = DHCPREQUEST;
bp->bp_vend[7] = TAG_REQ_ADDR;
bp->bp_vend[8] = 4;
bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
bp->bp_vend[13] = TAG_SERVERID;
bp->bp_vend[14] = 4;
bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
bp->bp_vend[19] = TAG_LEASETIME;
bp->bp_vend[20] = 4;
leasetime = htonl(300);
bcopy(&leasetime, &bp->bp_vend[21], 4);
bp->bp_vend[25] = TAG_END;
expected_dhcpmsgtype = DHCPACK;
if(sendrecv(d,
bootpsend, bp, sizeof(*bp),
bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
== -1) {
printf("DHCPREQUEST failed\n");
return;
}
}
#endif
myip = d->myip = rbuf.rbootp.bp_yiaddr;
servip = rbuf.rbootp.bp_siaddr;
if(rootip.s_addr == INADDR_ANY) rootip = servip;
bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
bootfile[sizeof(bootfile) - 1] = '\0';
if (IN_CLASSA(myip.s_addr))
nmask = htonl(IN_CLASSA_NET);
else if (IN_CLASSB(myip.s_addr))
nmask = htonl(IN_CLASSB_NET);
else
nmask = htonl(IN_CLASSC_NET);
#ifdef BOOTP_DEBUG
if (debug)
printf("'native netmask' is %s\n", intoa(nmask));
#endif
/* Check subnet mask against net mask; toss if bogus */
if ((nmask & smask) != nmask) {
#ifdef BOOTP_DEBUG
if (debug)
printf("subnet mask (%s) bad\n", intoa(smask));
#endif
smask = 0;
}
/* Get subnet (or natural net) mask */
netmask = nmask;
if (smask)
netmask = smask;
#ifdef BOOTP_DEBUG
if (debug)
printf("mask: %s\n", intoa(netmask));
#endif
/* We need a gateway if root is on a different net */
if (!SAMENET(myip, rootip, netmask)) {
#ifdef BOOTP_DEBUG
if (debug)
printf("need gateway for root ip\n");
#endif
}
/* Toss gateway if on a different net */
if (!SAMENET(myip, gateip, netmask)) {
#ifdef BOOTP_DEBUG
if (debug)
printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
#endif
gateip.s_addr = 0;
}
/* Bump xid so next request will be unique. */
++d->xid;
}
/* Transmit a bootp request */
static ssize_t
bootpsend(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register size_t len;
{
register struct bootp *bp;
#ifdef BOOTP_DEBUG
if (debug)
printf("bootpsend: d=%lx called.\n", (long)d);
#endif
bp = pkt;
bp->bp_secs = htons((u_short)(getsecs() - bot));
#ifdef BOOTP_DEBUG
if (debug)
printf("bootpsend: calling sendudp\n");
#endif
return (sendudp(d, pkt, len));
}
static ssize_t
bootprecv(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
{
register ssize_t n;
register struct bootp *bp;
#ifdef BOOTP_DEBUGx
if (debug)
printf("bootp_recvoffer: called\n");
#endif
n = readudp(d, pkt, len, tleft);
if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
goto bad;
bp = (struct bootp *)pkt;
#ifdef BOOTP_DEBUG
if (debug)
printf("bootprecv: checked. bp = 0x%lx, n = %d\n",
(long)bp, (int)n);
#endif
if (bp->bp_xid != htonl(d->xid)) {
#ifdef BOOTP_DEBUG
if (debug) {
printf("bootprecv: expected xid 0x%lx, got 0x%x\n",
d->xid, ntohl(bp->bp_xid));
}
#endif
goto bad;
}
#ifdef BOOTP_DEBUG
if (debug)
printf("bootprecv: got one!\n");
#endif
/* Suck out vendor info */
if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0)
goto bad;
}
#ifdef BOOTP_VEND_CMU
else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
vend_cmu(bp->bp_vend);
#endif
else
printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
return(n);
bad:
errno = 0;
return (-1);
}
static int
vend_rfc1048(cp, len)
register u_char *cp;
u_int len;
{
register u_char *ep;
register int size;
register u_char tag;
#ifdef BOOTP_DEBUG
if (debug)
printf("vend_rfc1048 bootp info. len=%d\n", len);
#endif
ep = cp + len;
/* Step over magic cookie */
cp += sizeof(int);
while (cp < ep) {
tag = *cp++;
size = *cp++;
if (tag == TAG_END)
break;
if (tag == TAG_SUBNET_MASK) {
bcopy(cp, &smask, sizeof(smask));
}
if (tag == TAG_GATEWAY) {
bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr));
}
if (tag == TAG_SWAPSERVER) {
/* let it override bp_siaddr */
bcopy(cp, &rootip.s_addr, sizeof(swapip.s_addr));
}
if (tag == TAG_ROOTPATH) {
strncpy(rootpath, (char *)cp, sizeof(rootpath));
rootpath[size] = '\0';
}
if (tag == TAG_HOSTNAME) {
strncpy(hostname, (char *)cp, sizeof(hostname));
hostname[size] = '\0';
}
#ifdef SUPPORT_DHCP
if (tag == TAG_DHCP_MSGTYPE) {
if(*cp != expected_dhcpmsgtype)
return(-1);
dhcp_ok = 1;
}
if (tag == TAG_SERVERID) {
bcopy(cp, &dhcp_serverip.s_addr,
sizeof(dhcp_serverip.s_addr));
}
#endif
cp += size;
}
return(0);
}
#ifdef BOOTP_VEND_CMU
static void
vend_cmu(cp)
u_char *cp;
{
register struct cmu_vend *vp;
#ifdef BOOTP_DEBUG
if (debug)
printf("vend_cmu bootp info.\n");
#endif
vp = (struct cmu_vend *)cp;
if (vp->v_smask.s_addr != 0) {
smask = vp->v_smask.s_addr;
}
if (vp->v_dgate.s_addr != 0) {
gateip = vp->v_dgate;
}
}
#endif

137
lib/libstand/bootp.h Normal file
View File

@ -0,0 +1,137 @@
/* $NetBSD: bootp.h,v 1.4 1997/09/06 13:55:57 drochner Exp $ */
/*
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
*
* This file specifies the "implementation-independent" BOOTP protocol
* information which is common to both client and server.
*
* Copyright 1988 by Carnegie Mellon.
*
* Permission to use, copy, modify, and distribute this program for any
* purpose and without fee is hereby granted, provided that this copyright
* and permission notice appear on all copies and supporting documentation,
* the name of Carnegie Mellon not be used in advertising or publicity
* pertaining to distribution of the program without specific prior
* permission, and notice be given in supporting documentation that copying
* and distribution is by permission of Carnegie Mellon and Stanford
* University. Carnegie Mellon makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
struct bootp {
unsigned char bp_op; /* packet opcode type */
unsigned char bp_htype; /* hardware addr type */
unsigned char bp_hlen; /* hardware addr length */
unsigned char bp_hops; /* gateway hops */
unsigned int bp_xid; /* transaction ID */
unsigned short bp_secs; /* seconds since boot began */
unsigned short bp_flags;
struct in_addr bp_ciaddr; /* client IP address */
struct in_addr bp_yiaddr; /* 'your' IP address */
struct in_addr bp_siaddr; /* server IP address */
struct in_addr bp_giaddr; /* gateway IP address */
unsigned char bp_chaddr[16]; /* client hardware address */
unsigned char bp_sname[64]; /* server host name */
unsigned char bp_file[128]; /* boot file name */
#ifdef SUPPORT_DHCP
#define BOOTP_VENDSIZE 312
#else
#define BOOTP_VENDSIZE 64
#endif
unsigned char bp_vend[BOOTP_VENDSIZE]; /* vendor-specific area */
};
/*
* UDP port numbers, server and client.
*/
#define IPPORT_BOOTPS 67
#define IPPORT_BOOTPC 68
#define BOOTREPLY 2
#define BOOTREQUEST 1
/*
* Vendor magic cookie (v_magic) for CMU
*/
#define VM_CMU "CMU"
/*
* Vendor magic cookie (v_magic) for RFC1048
*/
#define VM_RFC1048 { 99, 130, 83, 99 }
/*
* RFC1048 tag values used to specify what information is being supplied in
* the vendor field of the packet.
*/
#define TAG_PAD ((unsigned char) 0)
#define TAG_SUBNET_MASK ((unsigned char) 1)
#define TAG_TIME_OFFSET ((unsigned char) 2)
#define TAG_GATEWAY ((unsigned char) 3)
#define TAG_TIME_SERVER ((unsigned char) 4)
#define TAG_NAME_SERVER ((unsigned char) 5)
#define TAG_DOMAIN_SERVER ((unsigned char) 6)
#define TAG_LOG_SERVER ((unsigned char) 7)
#define TAG_COOKIE_SERVER ((unsigned char) 8)
#define TAG_LPR_SERVER ((unsigned char) 9)
#define TAG_IMPRESS_SERVER ((unsigned char) 10)
#define TAG_RLP_SERVER ((unsigned char) 11)
#define TAG_HOSTNAME ((unsigned char) 12)
#define TAG_BOOTSIZE ((unsigned char) 13)
#define TAG_DUMPFILE ((unsigned char) 14)
#define TAG_DOMAINNAME ((unsigned char) 15)
#define TAG_SWAPSERVER ((unsigned char) 16)
#define TAG_ROOTPATH ((unsigned char) 17)
#ifdef SUPPORT_DHCP
#define TAG_REQ_ADDR ((unsigned char) 50)
#define TAG_LEASETIME ((unsigned char) 51)
#define TAG_OVERLOAD ((unsigned char) 52)
#define TAG_DHCP_MSGTYPE ((unsigned char) 53)
#define TAG_SERVERID ((unsigned char) 54)
#define TAG_PARAM_REQ ((unsigned char) 55)
#define TAG_MSG ((unsigned char) 56)
#define TAG_MAXSIZE ((unsigned char) 57)
#define TAG_T1 ((unsigned char) 58)
#define TAG_T2 ((unsigned char) 59)
#define TAG_CLASSID ((unsigned char) 60)
#define TAG_CLIENTID ((unsigned char) 61)
#endif
#define TAG_END ((unsigned char) 255)
#ifdef SUPPORT_DHCP
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#endif
/*
* "vendor" data permitted for CMU bootp clients.
*/
struct cmu_vend {
unsigned char v_magic[4]; /* magic number */
unsigned int v_flags; /* flags/opcodes, etc. */
struct in_addr v_smask; /* Subnet mask */
struct in_addr v_dgate; /* Default gateway */
struct in_addr v_dns1, v_dns2; /* Domain name servers */
struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */
struct in_addr v_ts1, v_ts2; /* Time servers */
unsigned char v_unused[25]; /* currently unused */
};
/* v_flags values */
#define VF_SMASK 1 /* Subnet mask field contains valid data */

449
lib/libstand/bootparam.c Normal file
View File

@ -0,0 +1,449 @@
/* $NetBSD: bootparam.c,v 1.11 1997/06/26 19:11:32 drochner Exp $ */
/*
* Copyright (c) 1995 Gordon W. Ross
* 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. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
* 4. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Gordon W. Ross
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
*/
/*
* RPC/bootparams
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <string.h>
#include "rpcv2.h"
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "rpc.h"
#include "bootparam.h"
#ifdef DEBUG_RPC
#define RPC_PRINTF(a) printf a
#else
#define RPC_PRINTF(a)
#endif
struct in_addr bp_server_addr; /* net order */
n_short bp_server_port; /* net order */
/*
* RPC definitions for bootparamd
*/
#define BOOTPARAM_PROG 100026
#define BOOTPARAM_VERS 1
#define BOOTPARAM_WHOAMI 1
#define BOOTPARAM_GETFILE 2
/*
* Inet address in RPC messages
* (Note, really four ints, NOT chars. Blech.)
*/
struct xdr_inaddr {
u_int32_t atype;
int32_t addr[4];
};
int xdr_inaddr_encode(char **p, struct in_addr ia);
int xdr_inaddr_decode(char **p, struct in_addr *ia);
int xdr_string_encode(char **p, char *str, int len);
int xdr_string_decode(char **p, char *str, int *len_p);
/*
* RPC: bootparam/whoami
* Given client IP address, get:
* client name (hostname)
* domain name (domainname)
* gateway address
*
* The hostname and domainname are set here for convenience.
*
* Note - bpsin is initialized to the broadcast address,
* and will be replaced with the bootparam server address
* after this call is complete. Have to use PMAP_PROC_CALL
* to make sure we get responses only from a servers that
* know about us (don't want to broadcast a getport call).
*/
int
bp_whoami(sockfd)
int sockfd;
{
/* RPC structures for PMAPPROC_CALLIT */
struct args {
u_int32_t prog;
u_int32_t vers;
u_int32_t proc;
u_int32_t arglen;
struct xdr_inaddr xina;
} *args;
struct repl {
u_int16_t _pad;
u_int16_t port;
u_int32_t encap_len;
/* encapsulated data here */
n_long capsule[64];
} *repl;
struct {
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct repl d;
} rdata;
char *send_tail, *recv_head;
struct iodesc *d;
int len, x;
RPC_PRINTF(("bp_whoami: myip=%s\n", inet_ntoa(myip)));
if (!(d = socktodesc(sockfd))) {
RPC_PRINTF(("bp_whoami: bad socket. %d\n", sockfd));
return (-1);
}
args = &sdata.d;
repl = &rdata.d;
/*
* Build request args for PMAPPROC_CALLIT.
*/
args->prog = htonl(BOOTPARAM_PROG);
args->vers = htonl(BOOTPARAM_VERS);
args->proc = htonl(BOOTPARAM_WHOAMI);
args->arglen = htonl(sizeof(struct xdr_inaddr));
send_tail = (char*) &args->xina;
/*
* append encapsulated data (client IP address)
*/
if (xdr_inaddr_encode(&send_tail, myip))
return (-1);
/* RPC: portmap/callit */
d->myport = htons(--rpc_port);
d->destip.s_addr = INADDR_BROADCAST; /* XXX: subnet bcast? */
/* rpc_call will set d->destport */
len = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_CALLIT,
args, send_tail - (char*)args,
repl, sizeof(*repl));
if (len < 8) {
printf("bootparamd: 'whoami' call failed\n");
return (-1);
}
/* Save bootparam server address (from IP header). */
rpc_fromaddr(repl, &bp_server_addr, &bp_server_port);
/*
* Note that bp_server_port is now 111 due to the
* indirect call (using PMAPPROC_CALLIT), so get the
* actual port number from the reply data.
*/
bp_server_port = repl->port;
RPC_PRINTF(("bp_whoami: server at %s:%d\n",
inet_ntoa(bp_server_addr), ntohs(bp_server_port)));
/* We have just done a portmap call, so cache the portnum. */
rpc_pmap_putcache(bp_server_addr,
BOOTPARAM_PROG,
BOOTPARAM_VERS,
(int)ntohs(bp_server_port));
/*
* Parse the encapsulated results from bootparam/whoami
*/
x = ntohl(repl->encap_len);
if (len < x) {
printf("bp_whoami: short reply, %d < %d\n", len, x);
return (-1);
}
recv_head = (char*) repl->capsule;
/* client name */
hostnamelen = MAXHOSTNAMELEN-1;
if (xdr_string_decode(&recv_head, hostname, &hostnamelen)) {
RPC_PRINTF(("bp_whoami: bad hostname\n"));
return (-1);
}
/* domain name */
domainnamelen = MAXHOSTNAMELEN-1;
if (xdr_string_decode(&recv_head, domainname, &domainnamelen)) {
RPC_PRINTF(("bp_whoami: bad domainname\n"));
return (-1);
}
/* gateway address */
if (xdr_inaddr_decode(&recv_head, &gateip)) {
RPC_PRINTF(("bp_whoami: bad gateway\n"));
return (-1);
}
/* success */
return(0);
}
/*
* RPC: bootparam/getfile
* Given client name and file "key", get:
* server name
* server IP address
* server pathname
*/
int
bp_getfile(sockfd, key, serv_addr, pathname)
int sockfd;
char *key;
char *pathname;
struct in_addr *serv_addr;
{
struct {
n_long h[RPC_HEADER_WORDS];
n_long d[64];
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
n_long d[128];
} rdata;
char serv_name[FNAME_SIZE];
char *send_tail, *recv_head;
/* misc... */
struct iodesc *d;
int sn_len, path_len, rlen;
if (!(d = socktodesc(sockfd))) {
RPC_PRINTF(("bp_getfile: bad socket. %d\n", sockfd));
return (-1);
}
send_tail = (char*) sdata.d;
recv_head = (char*) rdata.d;
/*
* Build request message.
*/
/* client name (hostname) */
if (xdr_string_encode(&send_tail, hostname, hostnamelen)) {
RPC_PRINTF(("bp_getfile: bad client\n"));
return (-1);
}
/* key name (root or swap) */
if (xdr_string_encode(&send_tail, key, strlen(key))) {
RPC_PRINTF(("bp_getfile: bad key\n"));
return (-1);
}
/* RPC: bootparam/getfile */
d->myport = htons(--rpc_port);
d->destip = bp_server_addr;
/* rpc_call will set d->destport */
rlen = rpc_call(d,
BOOTPARAM_PROG, BOOTPARAM_VERS, BOOTPARAM_GETFILE,
sdata.d, send_tail - (char*)sdata.d,
rdata.d, sizeof(rdata.d));
if (rlen < 4) {
RPC_PRINTF(("bp_getfile: short reply\n"));
errno = EBADRPC;
return (-1);
}
recv_head = (char*) rdata.d;
/*
* Parse result message.
*/
/* server name */
sn_len = FNAME_SIZE-1;
if (xdr_string_decode(&recv_head, serv_name, &sn_len)) {
RPC_PRINTF(("bp_getfile: bad server name\n"));
return (-1);
}
/* server IP address (mountd/NFS) */
if (xdr_inaddr_decode(&recv_head, serv_addr)) {
RPC_PRINTF(("bp_getfile: bad server addr\n"));
return (-1);
}
/* server pathname */
path_len = MAXPATHLEN-1;
if (xdr_string_decode(&recv_head, pathname, &path_len)) {
RPC_PRINTF(("bp_getfile: bad server path\n"));
return (-1);
}
/* success */
return(0);
}
/*
* eXternal Data Representation routines.
* (but with non-standard args...)
*/
int
xdr_string_encode(pkt, str, len)
char **pkt;
char *str;
int len;
{
u_int32_t *lenp;
char *datap;
int padlen = (len + 3) & ~3; /* padded length */
/* The data will be int aligned. */
lenp = (u_int32_t*) *pkt;
*pkt += sizeof(*lenp);
*lenp = htonl(len);
datap = *pkt;
*pkt += padlen;
bcopy(str, datap, len);
return (0);
}
int
xdr_string_decode(pkt, str, len_p)
char **pkt;
char *str;
int *len_p; /* bufsize - 1 */
{
u_int32_t *lenp;
char *datap;
int slen; /* string length */
int plen; /* padded length */
/* The data will be int aligned. */
lenp = (u_int32_t*) *pkt;
*pkt += sizeof(*lenp);
slen = ntohl(*lenp);
plen = (slen + 3) & ~3;
if (slen > *len_p)
slen = *len_p;
datap = *pkt;
*pkt += plen;
bcopy(datap, str, slen);
str[slen] = '\0';
*len_p = slen;
return (0);
}
int
xdr_inaddr_encode(pkt, ia)
char **pkt;
struct in_addr ia; /* network order */
{
struct xdr_inaddr *xi;
u_char *cp;
int32_t *ip;
union {
n_long l; /* network order */
u_char c[4];
} uia;
/* The data will be int aligned. */
xi = (struct xdr_inaddr *) *pkt;
*pkt += sizeof(*xi);
xi->atype = htonl(1);
uia.l = ia.s_addr;
cp = uia.c;
ip = xi->addr;
/*
* Note: the htonl() calls below DO NOT
* imply that uia.l is in host order.
* In fact this needs it in net order.
*/
*ip++ = htonl((unsigned int)*cp++);
*ip++ = htonl((unsigned int)*cp++);
*ip++ = htonl((unsigned int)*cp++);
*ip++ = htonl((unsigned int)*cp++);
return (0);
}
int
xdr_inaddr_decode(pkt, ia)
char **pkt;
struct in_addr *ia; /* network order */
{
struct xdr_inaddr *xi;
u_char *cp;
int32_t *ip;
union {
n_long l; /* network order */
u_char c[4];
} uia;
/* The data will be int aligned. */
xi = (struct xdr_inaddr *) *pkt;
*pkt += sizeof(*xi);
if (xi->atype != htonl(1)) {
RPC_PRINTF(("xdr_inaddr_decode: bad addrtype=%d\n",
ntohl(xi->atype)));
return(-1);
}
cp = uia.c;
ip = xi->addr;
/*
* Note: the ntohl() calls below DO NOT
* imply that uia.l is in host order.
* In fact this needs it in net order.
*/
*cp++ = ntohl(*ip++);
*cp++ = ntohl(*ip++);
*cp++ = ntohl(*ip++);
*cp++ = ntohl(*ip++);
ia->s_addr = uia.l;
return (0);
}

5
lib/libstand/bootparam.h Normal file
View File

@ -0,0 +1,5 @@
/* $NetBSD: bootparam.h,v 1.3 1998/01/05 19:19:41 perry Exp $ */
int bp_whoami(int sock);
int bp_getfile(int sock, char *key, struct in_addr *addrp, char *path);

37
lib/libstand/bswap.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Written by Manuel Bouyer <bouyer@netbsd.org>.
* Public domain.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$NetBSD: bswap32.c,v 1.1 1997/10/09 15:42:33 bouyer Exp $";
static char *rcsid = "$NetBSD: bswap64.c,v 1.1 1997/10/09 15:42:33 bouyer Exp $";
#endif
#include <sys/types.h>
#undef bswap32
#undef bswap64
u_int32_t
bswap32(x)
u_int32_t x;
{
return ((x << 24) & 0xff000000 ) |
((x << 8) & 0x00ff0000 ) |
((x >> 8) & 0x0000ff00 ) |
((x >> 24) & 0x000000ff );
}
u_int64_t
bswap64(x)
u_int64_t x;
{
u_int32_t *p = (u_int32_t*)&x;
u_int32_t t;
t = bswap32(p[0]);
p[0] = bswap32(p[1]);
p[1] = t;
return x;
}

401
lib/libstand/cd9660.c Normal file
View File

@ -0,0 +1,401 @@
/* $NetBSD: cd9660.c,v 1.5 1997/06/26 19:11:33 drochner Exp $ */
/*
* Copyright (C) 1996 Wolfgang Solfrank.
* Copyright (C) 1996 TooLs GmbH.
* 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 TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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-alone ISO9660 file reading package.
*
* Note: This doesn't support Rock Ridge extensions, extended attributes,
* blocksizes other than 2048 bytes, multi-extent files, etc.
*/
#include <sys/param.h>
#include <string.h>
#include <isofs/cd9660/iso.h>
#include "stand.h"
static int cd9660_open(char *path, struct open_file *f);
static int cd9660_close(struct open_file *f);
static int cd9660_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static int cd9660_write(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t cd9660_seek(struct open_file *f, off_t offset, int where);
static int cd9660_stat(struct open_file *f, struct stat *sb);
struct fs_ops cd9660_fsops = {
"cd9660", cd9660_open, cd9660_close, cd9660_read, cd9660_write, cd9660_seek, cd9660_stat
};
struct file {
off_t off; /* Current offset within file */
daddr_t bno; /* Starting block number */
off_t size; /* Size of file */
};
struct ptable_ent {
char namlen [ISODCL( 1, 1)]; /* 711 */
char extlen [ISODCL( 2, 2)]; /* 711 */
char block [ISODCL( 3, 6)]; /* 732 */
char parent [ISODCL( 7, 8)]; /* 722 */
char name [1];
};
#define PTFIXSZ 8
#define PTSIZE(pp) roundup(PTFIXSZ + isonum_711((pp)->namlen), 2)
#define cdb2devb(bno) ((bno) * ISO_DEFAULT_BLOCK_SIZE / DEV_BSIZE)
/* XXX these should be in the system headers */
static __inline int
isonum_722(p)
u_char *p;
{
return (*p << 8)|p[1];
}
static __inline int
isonum_732(p)
u_char *p;
{
return (*p << 24)|(p[1] << 16)|(p[2] << 8)|p[3];
}
static int
pnmatch(path, pp)
char *path;
struct ptable_ent *pp;
{
char *cp;
int i;
cp = pp->name;
for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) {
if (toupper(*path) == *cp)
continue;
return 0;
}
if (*path != '/')
return 0;
return 1;
}
static int
dirmatch(path, dp)
char *path;
struct iso_directory_record *dp;
{
char *cp;
int i;
/* This needs to be a regular file */
if (dp->flags[0] & 6)
return 0;
cp = dp->name;
for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) {
if (!*path)
break;
if (toupper(*path) == *cp)
continue;
return 0;
}
if (*path)
return 0;
/*
* Allow stripping of trailing dots and the version number.
* Note that this will find the first instead of the last version
* of a file.
*/
if (i >= 0 && (*cp == ';' || *cp == '.')) {
/* This is to prevent matching of numeric extensions */
if (*cp == '.' && cp[1] != ';')
return 0;
while (--i >= 0)
if (*++cp != ';' && (*cp < '0' || *cp > '9'))
return 0;
}
return 1;
}
static int
cd9660_open(path, f)
char *path;
struct open_file *f;
{
struct file *fp = 0;
void *buf;
struct iso_primary_descriptor *vd;
size_t buf_size, read, psize, dsize;
daddr_t bno;
int parent, ent;
struct ptable_ent *pp;
struct iso_directory_record *dp = 0;
int rc;
/* First find the volume descriptor */
buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE);
vd = buf;
for (bno = 16;; bno++) {
twiddle();
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
ISO_DEFAULT_BLOCK_SIZE, buf, &read);
if (rc)
goto out;
if (read != ISO_DEFAULT_BLOCK_SIZE) {
rc = EIO;
goto out;
}
rc = EINVAL;
if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
goto out;
if (isonum_711(vd->type) == ISO_VD_END)
goto out;
if (isonum_711(vd->type) == ISO_VD_PRIMARY)
break;
}
if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
goto out;
/* Now get the path table and lookup the directory of the file */
bno = isonum_732(vd->type_m_path_table);
psize = isonum_733(vd->path_table_size);
if (psize > ISO_DEFAULT_BLOCK_SIZE) {
free(buf);
buf = malloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE));
}
twiddle();
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
buf_size, buf, &read);
if (rc)
goto out;
if (read != buf_size) {
rc = EIO;
goto out;
}
parent = 1;
pp = (struct ptable_ent *)buf;
ent = 1;
bno = isonum_732(pp->block) + isonum_711(pp->extlen);
rc = ENOENT;
while (*path) {
if ((void *)pp >= buf + psize)
break;
if (isonum_722(pp->parent) != parent)
break;
if (!pnmatch(path, pp)) {
pp = (struct ptable_ent *)((void *)pp + PTSIZE(pp));
ent++;
continue;
}
path += isonum_711(pp->namlen) + 1;
parent = ent;
bno = isonum_732(pp->block) + isonum_711(pp->extlen);
while ((void *)pp < buf + psize) {
if (isonum_722(pp->parent) == parent)
break;
pp = (struct ptable_ent *)((void *)pp + PTSIZE(pp));
ent++;
}
}
/* Now bno has the start of the directory that supposedly contains the file */
bno--;
dsize = 1; /* Something stupid, but > 0 XXX */
for (psize = 0; psize < dsize;) {
if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) {
bno++;
twiddle();
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ,
cdb2devb(bno),
ISO_DEFAULT_BLOCK_SIZE,
buf, &read);
if (rc)
goto out;
if (read != ISO_DEFAULT_BLOCK_SIZE) {
rc = EIO;
goto out;
}
dp = (struct iso_directory_record *)buf;
}
if (!isonum_711(dp->length)) {
if ((void *)dp == buf)
psize += ISO_DEFAULT_BLOCK_SIZE;
else
psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE);
continue;
}
if (dsize == 1)
dsize = isonum_733(dp->size);
if (dirmatch(path, dp))
break;
psize += isonum_711(dp->length);
dp = (struct iso_directory_record *)((void *)dp + isonum_711(dp->length));
}
if (psize >= dsize) {
rc = ENOENT;
goto out;
}
/* allocate file system specific data structure */
fp = malloc(sizeof(struct file));
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
fp->off = 0;
fp->bno = isonum_733(dp->extent);
fp->size = isonum_733(dp->size);
free(buf);
return 0;
out:
if (fp)
free(fp);
free(buf);
return rc;
}
static int
cd9660_close(f)
struct open_file *f;
{
struct file *fp = (struct file *)f->f_fsdata;
f->f_fsdata = 0;
free(fp);
return 0;
}
static int
cd9660_read(f, start, size, resid)
struct open_file *f;
void *start;
size_t size;
size_t *resid;
{
struct file *fp = (struct file *)f->f_fsdata;
int rc = 0;
daddr_t bno;
char buf[ISO_DEFAULT_BLOCK_SIZE];
char *dp;
size_t read, off;
while (size) {
if (fp->off < 0 || fp->off >= fp->size)
break;
bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno;
if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1)
|| size < ISO_DEFAULT_BLOCK_SIZE)
dp = buf;
else
dp = start;
twiddle();
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
ISO_DEFAULT_BLOCK_SIZE, dp, &read);
if (rc)
return rc;
if (read != ISO_DEFAULT_BLOCK_SIZE)
return EIO;
if (dp == buf) {
off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1);
if (read > off + size)
read = off + size;
read -= off;
bcopy(buf + off, start, read);
start += read;
fp->off += read;
size -= read;
} else {
start += ISO_DEFAULT_BLOCK_SIZE;
fp->off += ISO_DEFAULT_BLOCK_SIZE;
size -= ISO_DEFAULT_BLOCK_SIZE;
}
}
if (resid)
*resid = size;
return rc;
}
static int
cd9660_write(f, start, size, resid)
struct open_file *f;
void *start;
size_t size;
size_t *resid;
{
return EROFS;
}
static off_t
cd9660_seek(f, offset, where)
struct open_file *f;
off_t offset;
int where;
{
struct file *fp = (struct file *)f->f_fsdata;
switch (where) {
case SEEK_SET:
fp->off = offset;
break;
case SEEK_CUR:
fp->off += offset;
break;
case SEEK_END:
fp->off = fp->size - offset;
break;
default:
return -1;
}
return fp->off;
}
static int
cd9660_stat(f, sb)
struct open_file *f;
struct stat *sb;
{
struct file *fp = (struct file *)f->f_fsdata;
/* only importatn stuff */
sb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
sb->st_uid = sb->st_gid = 0;
sb->st_size = fp->size;
return 0;
}

96
lib/libstand/close.c Normal file
View File

@ -0,0 +1,96 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
int
close(fd)
int fd;
{
register struct open_file *f = &files[fd];
int err1 = 0, err2 = 0;
if ((unsigned)fd >= SOPEN_MAX || f->f_flags == 0) {
errno = EBADF;
return (-1);
}
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 (err1) {
errno = err1;
return (-1);
}
if (err2) {
errno = err2;
return (-1);
}
return (0);
}

77
lib/libstand/closeall.c Normal file
View File

@ -0,0 +1,77 @@
/* $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.
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
void
closeall()
{
int i;
for (i = 0; i < SOPEN_MAX; i++)
if (files[i].f_flags != 0)
(void)close(i);
}

62
lib/libstand/dev.c Normal file
View File

@ -0,0 +1,62 @@
/* $NetBSD: dev.c,v 1.4 1994/10/30 21:48:23 cgd 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)dev.c 8.1 (Berkeley) 6/11/93
*/
#include <sys/param.h>
#include <sys/reboot.h>
#include "stand.h"
int
nodev()
{
return (ENXIO);
}
void
nullsys()
{
}
/* ARGSUSED */
int
noioctl(f, cmd, data)
struct open_file *f;
u_long cmd;
void *data;
{
return (EINVAL);
}

255
lib/libstand/dev_net.c Normal file
View File

@ -0,0 +1,255 @@
/* $NetBSD: dev_net.c,v 1.12 1997/12/10 20:38:37 gwr Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Gordon W. Ross.
*
* 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 the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* This module implements a "raw device" interface suitable for
* use by the stand-alone I/O library NFS code. This interface
* does not support any "block" access, and exists only for the
* purpose of initializing the network interface, getting boot
* parameters, and performing the NFS mount.
*
* At open time, this does:
*
* find interface - netif_open()
* RARP for IP address - rarp_getipaddress()
* RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...)
* RPC/mountd - nfs_mount(sock, ip, path)
*
* the root file handle from mountd is saved in a global
* for use by the NFS open code (NFS/lookup).
*/
#include <machine/stdarg.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "nfs.h"
#include "bootparam.h"
#include "dev_net.h"
static int netdev_sock = -1;
static int netdev_opens;
static int net_getparams(int sock);
struct devsw netdev = {
"net",
DEVT_NET,
net_init,
net_strategy,
net_open,
net_close,
noioctl
};
/*
* Called by devopen after it sets f->f_dev to our devsw entry.
* This opens the low-level device and sets f->f_devdata.
* This is declared with variable arguments...
*/
int
net_open(struct open_file *f, void *vdev)
{
char *devname; /* Device part of file name (or NULL). */
int error = 0;
devname = vdev;
#ifdef NETIF_DEBUG
if (debug)
printf("net_open: %s\n", devname);
#endif
/* On first open, do netif open, mount, etc. */
if (netdev_opens == 0) {
/* Find network interface. */
if (netdev_sock < 0) {
netdev_sock = netif_open(devname);
if (netdev_sock < 0) {
printf("net_open: netif_open() failed\n");
return (ENXIO);
}
if (debug)
printf("net_open: netif_open() succeeded\n");
}
if (rootip.s_addr == 0) {
/* Get root IP address, and path, etc. */
error = net_getparams(netdev_sock);
if (error) {
/* getparams makes its own noise */
netif_close(netdev_sock);
netdev_sock = -1;
return (error);
}
}
}
netdev_opens++;
return (error);
}
int
net_close(f)
struct open_file *f;
{
#ifdef NETIF_DEBUG
if (debug)
printf("net_close: opens=%d\n", netdev_opens);
#endif
/* On last close, do netif close, etc. */
f->f_devdata = NULL;
/* Extra close call? */
if (netdev_opens <= 0)
return (0);
netdev_opens--;
/* Not last close? */
if (netdev_opens > 0)
return(0);
rootip.s_addr = 0;
if (netdev_sock >= 0) {
if (debug)
printf("net_close: calling netif_close()\n");
netif_close(netdev_sock);
netdev_sock = -1;
}
return (0);
}
int
net_ioctl()
{
return EIO;
}
int
net_strategy()
{
return EIO;
}
/*
* Get info for NFS boot: our IP address, our hostname,
* server IP address, and our root path on the server.
* There are two ways to do this: The old, Sun way,
* and the more modern, BOOTP way. (RFC951, RFC1048)
*
* The default is to use the Sun bootparams RPC
* (because that is what the kernel will do).
* MD code can make try_bootp initialied data,
* which will override this common definition.
*/
#ifdef SUPPORT_BOOTP
int try_bootp;
int bootp(int sock);
#endif
static int
net_getparams(sock)
int sock;
{
char buf[MAXHOSTNAMELEN];
n_long smask;
#ifdef SUPPORT_BOOTP
/*
* Try to get boot info using BOOTP. If we succeed, then
* the server IP address, gateway, and root path will all
* be initialized. If any remain uninitialized, we will
* use RARP and RPC/bootparam (the Sun way) to get them.
*/
if (try_bootp)
bootp(sock);
if (myip.s_addr != 0)
return (0);
if (debug)
printf("net_open: BOOTP failed, trying RARP/RPC...\n");
#endif
/*
* Use RARP to get our IP address. This also sets our
* netmask to the "natural" default for our address.
*/
if (rarp_getipaddress(sock)) {
printf("net_open: RARP failed\n");
return (EIO);
}
printf("net_open: client addr: %s\n", inet_ntoa(myip));
/* Get our hostname, server IP address, gateway. */
if (bp_whoami(sock)) {
printf("net_open: bootparam/whoami RPC failed\n");
return (EIO);
}
printf("net_open: client name: %s\n", hostname);
/*
* Ignore the gateway from whoami (unreliable).
* Use the "gateway" parameter instead.
*/
smask = 0;
gateip.s_addr = 0;
if (bp_getfile(sock, "gateway", &gateip, buf) == 0) {
/* Got it! Parse the netmask. */
smask = ip_convertaddr(buf);
}
if (smask) {
netmask = smask;
printf("net_open: subnet mask: %s\n", intoa(netmask));
}
if (gateip.s_addr)
printf("net_open: net gateway: %s\n", inet_ntoa(gateip));
/* Get the root server and pathname. */
if (bp_getfile(sock, "root", &rootip, rootpath)) {
printf("net_open: bootparam/getfile RPC failed\n");
return (EIO);
}
printf("net_open: server addr: %s\n", inet_ntoa(rootip));
printf("net_open: server path: %s\n", rootpath);
return (0);
}

7
lib/libstand/dev_net.h Normal file
View File

@ -0,0 +1,7 @@
/* $NetBSD: dev_net.h,v 1.3 1997/03/15 18:12:14 is Exp $ */
int net_open(struct open_file *, ...);
int net_close(struct open_file *);
int net_ioctl();
int net_strategy();

660
lib/libstand/dosfs.c Normal file
View File

@ -0,0 +1,660 @@
/*
* Copyright (c) 1996, 1998 Robert Nordier
* 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(S) ``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(S) 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.
*/
/*
* Readonly filesystem for Microsoft FAT12/FAT16/FAT32 filesystems,
* also supports VFAT.
*/
#include <sys/types.h>
#include <string.h>
#include <stddef.h>
#include "stand.h"
#if 0
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#endif
#include "dosfs.h"
static int dos_open(char *path, struct open_file *fd);
static int dos_close(struct open_file *fd);
static int dos_read(struct open_file *fd, void *buf, size_t size, size_t *resid);
static off_t dos_seek(struct open_file *fd, off_t offset, int whence);
static int dos_stat(struct open_file *fd, struct stat *sb);
struct fs_ops dos_fsops = {
"dosfs", dos_open, dos_close, dos_read, null_write, dos_seek, dos_stat
};
#define SECSIZ 512 /* sector size */
#define SSHIFT 9 /* SECSIZ shift */
#define DEPSEC 16 /* directory entries per sector */
#define DSHIFT 4 /* DEPSEC shift */
#define LOCLUS 2 /* lowest cluster number */
/* DOS "BIOS Parameter Block" */
typedef struct {
u_char secsiz[2]; /* sector size */
u_char spc; /* sectors per cluster */
u_char ressec[2]; /* reserved sectors */
u_char fats; /* FATs */
u_char dirents[2]; /* root directory entries */
u_char secs[2]; /* total sectors */
u_char media; /* media descriptor */
u_char spf[2]; /* sectors per FAT */
u_char spt[2]; /* sectors per track */
u_char heads[2]; /* drive heads */
u_char hidsec[4]; /* hidden sectors */
u_char lsecs[4]; /* huge sectors */
u_char lspf[4]; /* huge sectors per FAT */
u_char xflg[2]; /* flags */
u_char vers[2]; /* filesystem version */
u_char rdcl[4]; /* root directory start cluster */
u_char infs[2]; /* filesystem info sector */
u_char bkbs[2]; /* backup boot sector */
} DOS_BPB;
/* Initial portion of DOS boot sector */
typedef struct {
u_char jmp[3]; /* usually 80x86 'jmp' opcode */
u_char oem[8]; /* OEM name and version */
DOS_BPB bpb; /* BPB */
} DOS_BS;
/* Supply missing "." and ".." root directory entries */
static const char *const dotstr[2] = {".", ".."};
static DOS_DE dot[2] = {
{". ", " ", FA_DIR, {0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
{0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}},
{".. ", " ", FA_DIR, {0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}},
{0, 0}, {0x21, 0}, {0, 0}, {0, 0, 0, 0}}
};
/* The usual conversion macros to avoid multiplication and division */
#define bytsec(n) ((n) >> SSHIFT)
#define secbyt(s) ((s) << SSHIFT)
#define entsec(e) ((e) >> DSHIFT)
#define bytblk(fs, n) ((n) >> (fs)->bshift)
#define blkbyt(fs, b) ((b) << (fs)->bshift)
#define secblk(fs, s) ((s) >> ((fs)->bshift - SSHIFT))
#define blksec(fs, b) ((b) << ((fs)->bshift - SSHIFT))
/* Convert cluster number to offset within filesystem */
#define blkoff(fs, b) (secbyt((fs)->lsndta) + blkbyt(fs, (b) - LOCLUS))
/* Convert cluster number to logical sector number */
#define blklsn(fs, b) ((fs)->lsndta + blksec(fs, (b) - LOCLUS))
/* Convert cluster number to offset within FAT */
#define fatoff(sz, c) ((sz) == 12 ? (c) + ((c) >> 1) : \
(sz) == 16 ? (c) << 1 : \
(c) << 2)
/* Does cluster number reference a valid data cluster? */
#define okclus(fs, c) ((c) >= LOCLUS && (c) <= (fs)->xclus)
/* Get start cluster from directory entry */
#define stclus(sz, de) ((sz) != 32 ? cv2((de)->clus) : \
((u_int)cv2((de)->dex.h_clus) << 16) | \
cv2((de)->clus))
static int dosunmount(DOS_FS *);
static int parsebs(DOS_FS *, DOS_BS *);
static int namede(DOS_FS *, const char *, DOS_DE **);
static int lookup(DOS_FS *, u_int, const char *, DOS_DE **);
static void cp_xdnm(u_char *, DOS_XDE *);
static void cp_sfn(u_char *, DOS_DE *);
static int fatget(DOS_FS *, u_int *);
static int fatend(u_int, u_int);
static int ioread(DOS_FS *, u_int, void *, u_int);
static int iobuf(DOS_FS *, u_int);
static int ioget(struct open_file *, u_int, void *, u_int);
/*
* Mount DOS filesystem
*/
static int
dos_mount(DOS_FS *fs, struct open_file *fd)
{
int err;
bzero(fs, sizeof(DOS_FS));
fs->fd = fd;
if ((err = !(fs->buf = alloc(SECSIZ)) ? errno : 0) ||
(err = ioget(fs->fd, 0, fs->buf, 1)) ||
(err = parsebs(fs, (DOS_BS *)fs->buf))) {
(void)dosunmount(fs);
return(err);
}
return 0;
}
/*
* Unmount mounted filesystem
*/
static int
dos_unmount(DOS_FS *fs)
{
int err;
if (fs->links)
return(EBUSY);
if ((err = dosunmount(fs)))
return(err);
return 0;
}
/*
* Common code shared by dos_mount() and dos_unmount()
*/
static int
dosunmount(DOS_FS *fs)
{
if (fs->buf)
free(fs->buf, 0);
free(fs, 0);
return(0);
}
/*
* Open DOS file
*/
static int
dos_open(char *path, struct open_file *fd)
{
DOS_DE *de;
DOS_FILE *f;
DOS_FS *fs;
u_int size, clus;
int err = 0;
/* Allocate mount structure, associate with open */
fs = alloc(sizeof(DOS_FS));
if ((err = dos_mount(fs, fd)))
goto out;
if ((err = namede(fs, path, &de)))
goto out;
/* XXX we need to be able to open directories */
if (de->attr & FA_DIR) {
err = EISDIR;
goto out;
}
clus = stclus(fs->fatsz, de);
size = cv4(de->size);
if (!clus ^ !size || (clus && !okclus(fs, clus))) {
err = EINVAL;
goto out;
}
f = alloc(sizeof(DOS_FILE));
bzero(f, sizeof(DOS_FILE));
f->fs = fs;
fs->links++;
f->de = *de;
fd->f_fsdata = (void *)f;
out:
return(err);
}
/*
* Read from file
*/
static int
dos_read(struct open_file *fd, void *buf, size_t nbyte, size_t *resid)
{
u_int nb, off, clus, c, cnt, n;
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
int err = 0;
nb = (u_int)nbyte;
if (nb > (n = cv4(f->de.size) - f->offset))
nb = n;
off = f->offset;
if ((clus = stclus(f->fs->fatsz, &f->de)))
off &= f->fs->bsize - 1;
c = f->c;
cnt = nb;
while (cnt) {
n = 0;
if (!c) {
if ((c = clus))
n = bytblk(f->fs, f->offset);
} else if (!off)
n++;
while (n--) {
if ((err = fatget(f->fs, &c)))
goto out;
if (!okclus(f->fs, c)) {
err = EINVAL;
goto out;
}
}
if (!clus || (n = f->fs->bsize - off) > cnt)
n = cnt;
if ((err = ioread(f->fs, blkoff(f->fs, c) + off, buf, n)))
goto out;
f->offset += n;
f->c = c;
off = 0;
buf += n;
cnt -= n;
}
out:
if (resid)
*resid = cnt;
return(err);
}
/*
* Reposition within file
*/
static off_t
dos_seek(struct open_file *fd, off_t offset, int whence)
{
off_t off;
u_int size;
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
size = cv4(f->de.size);
switch (whence) {
case SEEK_SET:
off = 0;
break;
case SEEK_CUR:
off = f->offset;
break;
case SEEK_END:
off = size;
break;
default:
return(-1);
}
off += offset;
if (off < 0 || off > size)
return(-1);
f->offset = (u_int)off;
f->c = 0;
return(off);
}
/*
* Close open file
*/
static int
dos_close(struct open_file *fd)
{
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
DOS_FS *fs = f->fs;
f->fs->links--;
free(f, 0);
dos_unmount(fs);
return 0;
}
/*
* Return some stat information on a file.
*/
static int
dos_stat(struct open_file *fd, struct stat *sb)
{
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
/* only important stuff */
sb->st_mode = 0444;
sb->st_nlink = 1;
sb->st_uid = 0;
sb->st_gid = 0;
sb->st_size = cv4(f->de.size);
return (0);
}
/*
* Parse DOS boot sector
*/
static int
parsebs(DOS_FS *fs, DOS_BS *bs)
{
u_int sc;
if ((bs->jmp[0] != 0x69 &&
bs->jmp[0] != 0xe9 &&
(bs->jmp[0] != 0xeb || bs->jmp[2] != 0x90)) ||
bs->bpb.media < 0xf0)
return EINVAL;
if (cv2(bs->bpb.secsiz) != SECSIZ)
return EINVAL;
if (!(fs->spc = bs->bpb.spc) || fs->spc & (fs->spc - 1))
return EINVAL;
fs->bsize = secbyt(fs->spc);
fs->bshift = ffs(fs->bsize) - 1;
if ((fs->spf = cv2(bs->bpb.spf))) {
if (bs->bpb.fats != 2)
return EINVAL;
if (!(fs->dirents = cv2(bs->bpb.dirents)))
return EINVAL;
} else {
if (!(fs->spf = cv4(bs->bpb.lspf)))
return EINVAL;
if (!bs->bpb.fats || bs->bpb.fats > 16)
return EINVAL;
if ((fs->rdcl = cv4(bs->bpb.rdcl)) < LOCLUS)
return EINVAL;
}
if (!(fs->lsnfat = cv2(bs->bpb.ressec)))
return EINVAL;
fs->lsndir = fs->lsnfat + fs->spf * bs->bpb.fats;
fs->lsndta = fs->lsndir + entsec(fs->dirents);
if (!(sc = cv2(bs->bpb.secs)) && !(sc = cv4(bs->bpb.lsecs)))
return EINVAL;
if (fs->lsndta > sc)
return EINVAL;
if ((fs->xclus = secblk(fs, sc - fs->lsndta) + 1) < LOCLUS)
return EINVAL;
fs->fatsz = fs->dirents ? fs->xclus < 0xff6 ? 12 : 16 : 32;
sc = (secbyt(fs->spf) << 1) / (fs->fatsz >> 2) - 1;
if (fs->xclus > sc)
fs->xclus = sc;
return 0;
}
/*
* Return directory entry from path
*/
static int
namede(DOS_FS *fs, const char *path, DOS_DE **dep)
{
char name[256];
DOS_DE *de;
char *s;
size_t n;
int err;
err = 0;
de = dot;
if (*path == '/')
path++;
while (*path) {
if (!(s = strchr(path, '/')))
s = strchr(path, 0);
if ((n = s - path) > 255)
return ENAMETOOLONG;
memcpy(name, path, n);
name[n] = 0;
path = s;
if (!(de->attr & FA_DIR))
return ENOTDIR;
if ((err = lookup(fs, stclus(fs->fatsz, de), name, &de)))
return err;
if (*path == '/')
path++;
}
*dep = de;
return 0;
}
/*
* Lookup path segment
*/
static int
lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep)
{
static DOS_DIR dir[DEPSEC];
u_char lfn[261];
u_char sfn[13];
u_int nsec, lsec, xdn, chk, sec, ent, x;
int err, ok, i;
if (!clus)
for (ent = 0; ent < 2; ent++)
if (!strcasecmp(name, dotstr[ent])) {
*dep = dot + ent;
return 0;
}
if (!clus && fs->fatsz == 32)
clus = fs->rdcl;
nsec = !clus ? entsec(fs->dirents) : fs->spc;
lsec = 0;
xdn = chk = 0;
for (;;) {
if (!clus && !lsec)
lsec = fs->lsndir;
else if (okclus(fs, clus))
lsec = blklsn(fs, clus);
else
return EINVAL;
for (sec = 0; sec < nsec; sec++) {
if ((err = ioget(fs->fd, lsec + sec, dir, 1)))
return err;
for (ent = 0; ent < DEPSEC; ent++) {
if (!*dir[ent].de.name)
return ENOENT;
if (*dir[ent].de.name != 0xe5)
if ((dir[ent].de.attr & FA_MASK) == FA_XDE) {
x = dir[ent].xde.seq;
if (x & 0x40 || (x + 1 == xdn &&
dir[ent].xde.chk == chk)) {
if (x & 0x40) {
chk = dir[ent].xde.chk;
x &= ~0x40;
}
if (x >= 1 && x <= 20) {
cp_xdnm(lfn, &dir[ent].xde);
xdn = x;
continue;
}
}
} else if (!(dir[ent].de.attr & FA_LABEL)) {
if ((ok = xdn == 1)) {
for (x = 0, i = 0; i < 11; i++)
x = ((((x & 1) << 7) | (x >> 1)) +
dir[ent].de.name[i]) & 0xff;
ok = chk == x &&
!strcasecmp(name, (const char *)lfn);
}
if (!ok) {
cp_sfn(sfn, &dir[ent].de);
ok = !strcasecmp(name, (const char *)sfn);
}
if (ok) {
*dep = &dir[ent].de;
return 0;
}
}
xdn = 0;
}
}
if (!clus)
break;
if ((err = fatget(fs, &clus)))
return err;
if (fatend(fs->fatsz, clus))
break;
}
return ENOENT;
}
/*
* Copy name from extended directory entry
*/
static void
cp_xdnm(u_char *lfn, DOS_XDE *xde)
{
static struct {
u_int off;
u_int dim;
} ix[3] = {
{offsetof(DOS_XDE, name1), sizeof(xde->name1) / 2},
{offsetof(DOS_XDE, name2), sizeof(xde->name2) / 2},
{offsetof(DOS_XDE, name3), sizeof(xde->name3) / 2}
};
u_char *p;
u_int n, x, c;
lfn += 13 * ((xde->seq & ~0x40) - 1);
for (n = 0; n < 3; n++)
for (p = (u_char *)xde + ix[n].off, x = ix[n].dim; x;
p += 2, x--) {
if ((c = cv2(p)) && (c < 32 || c > 127))
c = '?';
if (!(*lfn++ = c))
return;
}
if (xde->seq & 0x40)
*lfn = 0;
}
/*
* Copy short filename
*/
static void
cp_sfn(u_char *sfn, DOS_DE *de)
{
u_char *p;
int j, i;
p = sfn;
if (*de->name != ' ') {
for (j = 7; de->name[j] == ' '; j--);
for (i = 0; i <= j; i++)
*p++ = de->name[i];
if (*de->ext != ' ') {
*p++ = '.';
for (j = 2; de->ext[j] == ' '; j--);
for (i = 0; i <= j; i++)
*p++ = de->ext[i];
}
}
*p = 0;
if (*sfn == 5)
*sfn = 0xe5;
}
/*
* Get next cluster in cluster chain
*/
static int
fatget(DOS_FS *fs, u_int *c)
{
u_char buf[4];
u_int x;
int err;
err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf,
fs->fatsz != 32 ? 2 : 4);
if (err)
return err;
x = fs->fatsz != 32 ? cv2(buf) : cv4(buf);
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x;
return 0;
}
/*
* Is cluster an end-of-chain marker?
*/
static int
fatend(u_int sz, u_int c)
{
return c > (sz == 12 ? 0xff7U : sz == 16 ? 0xfff7U : 0xffffff7);
}
/*
* Offset-based I/O primitive
*/
static int
ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte)
{
char *s;
u_int off, n;
int err;
s = buf;
if ((off = offset & (SECSIZ - 1))) {
offset -= off;
if ((err = iobuf(fs, bytsec(offset))))
return err;
offset += SECSIZ;
if ((n = SECSIZ - off) > nbyte)
n = nbyte;
memcpy(s, fs->buf + off, n);
s += n;
nbyte -= n;
}
n = nbyte & (SECSIZ - 1);
if (nbyte -= n) {
if ((err = ioget(fs->fd, bytsec(offset), s, bytsec(nbyte))))
return err;
offset += nbyte;
s += nbyte;
}
if (n) {
if ((err = iobuf(fs, bytsec(offset))))
return err;
memcpy(s, fs->buf, n);
}
return 0;
}
/*
* Buffered sector-based I/O primitive
*/
static int
iobuf(DOS_FS *fs, u_int lsec)
{
int err;
if (fs->bufsec != lsec) {
if ((err = ioget(fs->fd, lsec, fs->buf, 1)))
return err;
fs->bufsec = lsec;
}
return 0;
}
/*
* Sector-based I/O primitive
*/
static int
ioget(struct open_file *fd, u_int lsec, void *buf, u_int nsec)
{
int err;
if ((err = (fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec,
secbyt(nsec), buf, NULL)))
return(err);
return(0);
}

120
lib/libstand/dosfs.h Normal file
View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 1996, 1998 Robert Nordier
* 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(S) ``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(S) 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.
*/
#ifndef DOSIO_H
#define DOSIO_H
/*
* DOS file attributes
*/
#define FA_RDONLY 001 /* read-only */
#define FA_HIDDEN 002 /* hidden file */
#define FA_SYSTEM 004 /* system file */
#define FA_LABEL 010 /* volume label */
#define FA_DIR 020 /* directory */
#define FA_ARCH 040 /* archive (file modified) */
#define FA_XDE 017 /* extended directory entry */
#define FA_MASK 077 /* all attributes */
/*
* Macros to convert DOS-format 16-bit and 32-bit quantities
*/
#define cv2(p) ((u_int16_t)(p)[0] | \
((u_int16_t)(p)[1] << 010))
#define cv4(p) ((u_int32_t)(p)[0] | \
((u_int32_t)(p)[1] << 010) | \
((u_int32_t)(p)[2] << 020) | \
((u_int32_t)(p)[3] << 030))
/*
* Directory, filesystem, and file structures.
*/
typedef struct {
u_char x_case; /* case */
u_char c_hsec; /* created: secs/100 */
u_char c_time[2]; /* created: time */
u_char c_date[2]; /* created: date */
u_char a_date[2]; /* accessed: date */
u_char h_clus[2]; /* clus[hi] */
} DOS_DEX;
typedef struct {
u_char name[8]; /* name */
u_char ext[3]; /* extension */
u_char attr; /* attributes */
DOS_DEX dex; /* VFAT/FAT32 only */
u_char time[2]; /* modified: time */
u_char date[2]; /* modified: date */
u_char clus[2]; /* starting cluster */
u_char size[4]; /* size */
} DOS_DE;
typedef struct {
u_char seq; /* flags */
u_char name1[5][2]; /* 1st name area */
u_char attr; /* (see fat_de) */
u_char res; /* reserved */
u_char chk; /* checksum */
u_char name2[6][2]; /* 2nd name area */
u_char clus[2]; /* (see fat_de) */
u_char name3[2][2]; /* 3rd name area */
} DOS_XDE;
typedef union {
DOS_DE de; /* standard directory entry */
DOS_XDE xde; /* extended directory entry */
} DOS_DIR;
typedef struct {
struct open_file *fd; /* file descriptor */
u_char *buf; /* buffer */
u_int bufsec; /* buffered sector */
u_int links; /* active links to structure */
u_int spc; /* sectors per cluster */
u_int bsize; /* cluster size in bytes */
u_int bshift; /* cluster conversion shift */
u_int dirents; /* root directory entries */
u_int spf; /* sectors per fat */
u_int rdcl; /* root directory start cluster */
u_int lsnfat; /* start of fat */
u_int lsndir; /* start of root dir */
u_int lsndta; /* start of data area */
u_int fatsz; /* FAT entry size */
u_int xclus; /* maximum cluster number */
} DOS_FS;
typedef struct {
DOS_FS *fs; /* associated filesystem */
DOS_DE de; /* directory entry */
u_int offset; /* current offset */
u_int c; /* last cluster read */
} DOS_FILE;
#endif /* !DOSIO_H */

212
lib/libstand/environment.c Normal file
View File

@ -0,0 +1,212 @@
/*
* 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.
*
* $Id$
*
*/
/*
* Manage an environment-like space in which string variables may be stored.
* Provide support for some method-like operations for setting/retrieving
* variables in order to allow some type strength.
*/
#include "stand.h"
#include <string.h>
static void env_discard(struct env_var *ev);
struct env_var *environ = NULL;
/*
* Look up (name) and return it's env_var structure.
*/
struct env_var *
env_getenv(const char *name)
{
struct env_var *ev;
for (ev = environ; ev != NULL; ev = ev->ev_next)
if (!strcmp(ev->ev_name, name))
break;
return(ev);
}
/*
* Some notes:
*
* If the EV_VOLATILE flag is set, a copy of the variable is made.
* If EV_DYNAMIC is set, the the variable has been allocated with
* malloc and ownership transferred to the environment.
* If (value) is NULL, the variable is set but has no value.
*/
int
env_setenv(const char *name, int flags, void *value, ev_sethook_t sethook,
ev_unsethook_t unsethook)
{
struct env_var *ev, *curr, *last;
if ((ev = env_getenv(name)) != NULL) {
/*
* If there's a set hook, let it do the work (unless we are working
* for one already.
*/
if ((ev->ev_sethook != NULL) && !(flags & EV_NOHOOK))
return(ev->ev_sethook(ev, flags, value));
} else {
ev = malloc(sizeof(struct env_var));
ev->ev_name = strdup(name);
ev->ev_value = NULL;
/* hooks can only be set when the variable is instantiated */
ev->ev_sethook = sethook;
ev->ev_unsethook = unsethook;
}
/* If there is data in the variable, discard it */
if (ev->ev_value != NULL)
free(ev->ev_value);
/* If we have a new value, use it */
if (flags & EV_VOLATILE) {
ev->ev_value = strdup(value);
} else {
ev->ev_value = value;
}
/* Keep the flag components that are relevant */
ev->ev_flags = flags & (EV_DYNAMIC);
/* Sort into list */
ev->ev_prev = NULL;
ev->ev_next = NULL;
/* Search for the record to insert before */
for (last = NULL, curr = environ;
curr != NULL;
last = curr, curr = curr->ev_next) {
if (strcmp(ev->ev_name, curr->ev_name) < 0) {
if (curr->ev_prev) {
curr->ev_prev->ev_next = ev;
} else {
environ = ev;
}
ev->ev_next = curr;
ev->ev_prev = curr->ev_prev;
curr->ev_prev = ev;
break;
}
}
if (curr == NULL) {
if (last == NULL) {
environ = ev;
} else {
last->ev_next = ev;
ev->ev_prev = last;
}
}
return(0);
}
char *
getenv(const char *name)
{
struct env_var *ev;
/* Set but no value gives empty string */
if ((ev = env_getenv(name)) != NULL) {
if (ev->ev_value != NULL)
return(ev->ev_value);
return("");
}
return(NULL);
}
int
setenv(const char *name, char *value, int overwrite)
{
/* No guarantees about state, always assume volatile */
if (overwrite || (env_getenv(name) == NULL))
return(env_setenv(name, EV_VOLATILE, value, NULL, NULL));
return(0);
}
int
putenv(const char *string)
{
char *value;
if ((value = strchr(string, '=')) != NULL)
*(value++) = 0;
return(setenv(string, value, 1));
}
int
unsetenv(const char *name)
{
struct env_var *ev;
int err;
err = 0;
if ((ev = env_getenv(name)) == NULL) {
err = ENOENT;
} else {
if (ev->ev_unsethook != NULL)
err = ev->ev_unsethook(ev);
if (err == 0) {
env_discard(ev);
}
}
return(err);
}
static void
env_discard(struct env_var *ev)
{
if (ev->ev_prev)
ev->ev_prev->ev_next = ev->ev_next;
if (ev->ev_next)
ev->ev_next->ev_prev = ev->ev_prev;
if (environ == ev)
environ = ev->ev_next;
free(ev->ev_name);
if (ev->ev_flags & EV_DYNAMIC)
free(ev->ev_value);
free(ev);
}
int
env_noset(struct env_var *ev, int flags, void *value)
{
return(EPERM);
}
int
env_nounset(struct env_var *ev)
{
return(EPERM);
}

151
lib/libstand/ether.c Normal file
View File

@ -0,0 +1,151 @@
/* $NetBSD: ether.c,v 1.11 1997/07/07 15:52:50 drochner Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL)
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <string.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
/* Caller must leave room for ethernet header in front!! */
ssize_t
sendether(d, pkt, len, dea, etype)
struct iodesc *d;
void *pkt;
size_t len;
u_char *dea;
int etype;
{
register ssize_t n;
register struct ether_header *eh;
#ifdef ETHER_DEBUG
if (debug)
printf("sendether: called\n");
#endif
eh = (struct ether_header *)pkt - 1;
len += sizeof(*eh);
MACPY(d->myea, eh->ether_shost); /* by byte */
MACPY(dea, eh->ether_dhost); /* by byte */
eh->ether_type = htons(etype);
n = netif_put(d, eh, len);
if (n == -1 || n < sizeof(*eh))
return (-1);
n -= sizeof(*eh);
return (n);
}
/*
* Get a packet of any Ethernet type, with our address or
* the broadcast address. Save the Ether type in arg 5.
* NOTE: Caller must leave room for the Ether header.
*/
ssize_t
readether(d, pkt, len, tleft, etype)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
register u_int16_t *etype;
{
register ssize_t n;
register struct ether_header *eh;
#ifdef ETHER_DEBUG
if (debug)
printf("readether: called\n");
#endif
eh = (struct ether_header *)pkt - 1;
len += sizeof(*eh);
n = netif_get(d, eh, len, tleft);
if (n == -1 || n < sizeof(*eh))
return (-1);
/* Validate Ethernet address. */
if (bcmp(d->myea, eh->ether_dhost, 6) != 0 &&
bcmp(bcea, eh->ether_dhost, 6) != 0) {
#ifdef ETHER_DEBUG
if (debug)
printf("readether: not ours (ea=%s)\n",
ether_sprintf(eh->ether_dhost));
#endif
return (-1);
}
*etype = ntohs(eh->ether_type);
n -= sizeof(*eh);
return (n);
}
/*
* Convert Ethernet address to printable (loggable) representation.
*/
static char digits[] = "0123456789abcdef";
char *
ether_sprintf(ap)
register u_char *ap;
{
register i;
static char etherbuf[18];
register char *cp = etherbuf;
for (i = 0; i < 6; i++) {
*cp++ = digits[*ap >> 4];
*cp++ = digits[*ap++ & 0xf];
*cp++ = ':';
}
*--cp = 0;
return (etherbuf);
}

60
lib/libstand/fstat.c Normal file
View File

@ -0,0 +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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
int
fstat(fd, sb)
int fd;
struct stat *sb;
{
register struct open_file *f = &files[fd];
if ((unsigned)fd >= SOPEN_MAX || 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);
return (0);
}

112
lib/libstand/getopt.c Normal file
View File

@ -0,0 +1,112 @@
/*
* Copyright (c) 1987, 1993, 1994
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
#endif /* LIBC_SCCS and not lint */
#include "stand.h"
#include <string.h>
int opterr = 1, /* if error message should be printed */
optind = 1, /* index into parent argv vector */
optopt, /* character checked for validity */
optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""
/*
* getopt --
* Parse argc/argv argument vector.
*/
int
getopt(nargc, nargv, ostr)
int nargc;
char * const *nargv;
const char *ostr;
{
static char *place = EMSG; /* option letter processing */
char *oli; /* option letter list index */
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-') { /* found "--" */
++optind;
place = EMSG;
return (-1);
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' ||
!(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
if (opterr && *ostr != ':')
(void)printf("illegal option -- %c\n", optopt);
return (BADCH);
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
(void)printf("option requires an argument -- %c\n", optopt);
return (BADCH);
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt); /* dump back option letter */
}

110
lib/libstand/gets.c Normal file
View File

@ -0,0 +1,110 @@
/* $NetBSD: gets.c,v 1.6 1995/10/11 21:16:57 pk 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)gets.c 8.1 (Berkeley) 6/11/93
*/
#include "stand.h"
/* gets() with constrained input length */
void
ngets(char *buf, int n)
{
register int c;
register char *lp;
for (lp = buf;;)
switch (c = getchar() & 0177) {
case '\n':
case '\r':
*lp = '\0';
putchar('\n');
return;
case '\b':
case '\177':
if (lp > buf) {
lp--;
putchar('\b');
putchar(' ');
putchar('\b');
}
break;
case 'r'&037: {
register char *p;
putchar('\n');
for (p = buf; p < lp; ++p)
putchar(*p);
break;
}
case 'u'&037:
case 'w'&037:
lp = buf;
putchar('\n');
break;
default:
if ((n < 1) || ((lp - buf) < n)) {
*lp++ = c;
putchar(c);
}
}
/*NOTREACHED*/
}
int
fgetstr(char *buf, int size, int fd)
{
char c;
int err, len;
size--; /* leave space for terminator */
len = 0;
while (size != 0) {
err = read(fd, &c, sizeof(c));
if (err < 0) /* read error */
return(-1);
if (err == 0) /* EOF */
break;
if ((c == '\r') || /* line terminators */
(c == '\n'))
break;
*buf++ = c; /* keep char */
size--;
len++;
}
*buf = 0;
return(len);
}

33
lib/libstand/globals.c Normal file
View File

@ -0,0 +1,33 @@
/* $NetBSD: globals.c,v 1.3 1995/09/18 21:19:27 pk Exp $ */
/*
* globals.c:
*
* global variables should be separate, so nothing else
* must be included extraneously.
*/
#include <sys/param.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "stand.h"
#include "net.h"
u_char bcea[6] = BA; /* broadcast ethernet address */
char rootpath[FNAME_SIZE] = "/"; /* root mount path */
char bootfile[FNAME_SIZE]; /* bootp says to boot this */
char hostname[FNAME_SIZE]; /* our hostname */
int hostnamelen;
char domainname[FNAME_SIZE]; /* our DNS domain */
int domainnamelen;
char ifname[IFNAME_SIZE]; /* name of interface (e.g. "le0") */
struct in_addr myip; /* my ip address */
struct in_addr nameip; /* DNS server ip address */
struct in_addr rootip; /* root ip address */
struct in_addr swapip; /* swap ip address */
struct in_addr gateip; /* swap ip address */
n_long netmask = 0xffffff00; /* subnet or net mask */
int errno; /* our old friend */

316
lib/libstand/gzipfs.c Normal file
View File

@ -0,0 +1,316 @@
/*
* 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.
*
* $Id$
*
*/
#include "stand.h"
#include <sys/stat.h>
#include <string.h>
#include <zlib.h>
#define Z_BUFSIZE 2048 /* XXX larger? */
struct z_file
{
int zf_rawfd;
z_stream zf_zstream;
char zf_buf[Z_BUFSIZE];
};
static int zf_fill(struct z_file *z);
static int zf_open(char *path, struct open_file *f);
static int zf_close(struct open_file *f);
static int zf_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t zf_seek(struct open_file *f, off_t offset, int where);
static int zf_stat(struct open_file *f, struct stat *sb);
struct fs_ops zipfs_fsops = {
"zip",
zf_open,
zf_close,
zf_read,
null_write,
zf_seek,
zf_stat
};
void *
calloc(int items, size_t size)
{
return(malloc(items * size));
}
static int
zf_fill(struct z_file *zf)
{
int result;
int req;
req = Z_BUFSIZE - zf->zf_zstream.avail_in;
result = 0;
/* If we need more */
if (req > 0) {
/* move old data to bottom of buffer */
if (req < Z_BUFSIZE)
bcopy(zf->zf_buf + req, zf->zf_buf, Z_BUFSIZE - req);
/* read to fill buffer and update availibility data */
result = read(zf->zf_rawfd, zf->zf_buf + zf->zf_zstream.avail_in, req);
zf->zf_zstream.next_in = zf->zf_buf;
if (result >= 0)
zf->zf_zstream.avail_in += result;
}
return(result);
}
/*
* Adapted from get_byte/check_header in libz
*
* Returns 0 if the header is OK, nonzero if not.
*/
static int
get_byte(struct z_file *zf)
{
if ((zf->zf_zstream.avail_in == 0) && (zf_fill(zf) == -1))
return(-1);
zf->zf_zstream.avail_in--;
return(*(zf->zf_zstream.next_in)++);
}
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
static int
check_header(struct z_file *zf)
{
int method; /* method byte */
int flags; /* flags byte */
uInt len;
int c;
/* Check the gzip magic header */
for (len = 0; len < 2; len++) {
c = get_byte(zf);
if (c != gz_magic[len]) {
return(1);
}
}
method = get_byte(zf);
flags = get_byte(zf);
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
return(1);
}
/* Discard time, xflags and OS code: */
for (len = 0; len < 6; len++) (void)get_byte(zf);
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
len = (uInt)get_byte(zf);
len += ((uInt)get_byte(zf))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && get_byte(zf) != -1) ;
}
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
while ((c = get_byte(zf)) != 0 && c != -1) ;
}
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
while ((c = get_byte(zf)) != 0 && c != -1) ;
}
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) c = get_byte(zf);
}
/* if there's data left, we're in business */
return((c == -1) ? 1 : 0);
}
static int
zf_open(char *fname, struct open_file *f)
{
static char *zfname;
int rawfd;
struct z_file *zf;
char *cp;
int error;
struct stat sb;
/* Have to be in "just read it" mode */
if (f->f_flags != F_READ)
return(EPERM);
/* If the name already ends in .gz, ignore it */
if ((cp = strrchr(fname, '.')) && !strcmp(cp, ".gz"))
return(ENOENT);
/* Construct new name */
zfname = malloc(strlen(fname) + 3);
sprintf(zfname, "%s.gz", fname);
/* Try to open the compressed datafile */
rawfd = open(zfname, O_RDONLY);
free(zfname);
if (rawfd == -1)
return(ENOENT);
if (fstat(rawfd, &sb) < 0) {
printf("zf_open: stat failed\n");
close(rawfd);
return(ENOENT);
}
if (!S_ISREG(sb.st_mode)) {
printf("zf_open: not a file\n");
close(rawfd);
return(EISDIR); /* best guess */
}
/* Allocate a z_file structure, populate it */
zf = malloc(sizeof(struct z_file));
bzero(zf, sizeof(struct z_file));
zf->zf_rawfd = rawfd;
/* Verify that the file is gzipped (XXX why do this afterwards?) */
if (check_header(zf)) {
close(zf->zf_rawfd);
inflateEnd(&(zf->zf_zstream));
free(zf);
return(EFTYPE);
}
/* Initialise the inflation engine */
if ((error = inflateInit2(&(zf->zf_zstream), -15)) != Z_OK) {
printf("zf_open: inflateInit returned %d : %s\n", error, zf->zf_zstream.msg);
close(zf->zf_rawfd);
free(zf);
return(EIO);
}
/* Looks OK, we'll take it */
f->f_fsdata = zf;
return(0);
}
static int
zf_close(struct open_file *f)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
inflateEnd(&(zf->zf_zstream));
close(zf->zf_rawfd);
free(zf);
return(0);
}
static int
zf_read(struct open_file *f, void *buf, size_t size, size_t *resid)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
int error;
zf->zf_zstream.next_out = buf; /* where and how much */
zf->zf_zstream.avail_out = size;
while (zf->zf_zstream.avail_out) {
if ((zf->zf_zstream.avail_in == 0) && (zf_fill(zf) == -1)) {
printf("zf_read: fill error\n");
return(-1);
}
if (zf->zf_zstream.avail_in == 0) { /* oops, unexpected EOF */
printf("zf_read: unexpected EOF\n");
break;
}
error = inflate(&zf->zf_zstream, Z_SYNC_FLUSH); /* decompression pass */
if (error == Z_STREAM_END) { /* EOF, all done */
break;
}
if (error != Z_OK) { /* argh, decompression error */
printf("inflate: %s\n", zf->zf_zstream.msg);
errno = EIO;
return(-1);
}
}
if (resid != NULL)
*resid = zf->zf_zstream.avail_out;
return(0);
}
static off_t
zf_seek(struct open_file *f, off_t offset, int where)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
off_t target;
char discard[16];
switch (where) {
case SEEK_SET:
target = offset;
break;
case SEEK_CUR:
target = offset + zf->zf_zstream.total_out;
break;
default:
target = -1;
}
/* Can we get there from here? */
if (target < zf->zf_zstream.total_out) {
errno = EOFFSET;
return -1;
}
/* skip forwards if required */
while (target > zf->zf_zstream.total_out) {
if (zf_read(f, discard, min(sizeof(discard), target - zf->zf_zstream.total_out), NULL) == -1)
return(-1);
}
/* This is where we are (be honest if we overshot) */
return (zf->zf_zstream.total_out);
}
static int
zf_stat(struct open_file *f, struct stat *sb)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
int result;
/* stat as normal, but indicate that size is unknown */
if ((result = fstat(zf->zf_rawfd, sb)) == 0)
sb->st_size = -1;
return(result);
}

263
lib/libstand/if_ether.h Normal file
View File

@ -0,0 +1,263 @@
/* $NetBSD: if_ether.h,v 1.25 1997/01/17 17:06:06 mikel Exp $ */
/*
* Copyright (c) 1982, 1986, 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)if_ether.h 8.1 (Berkeley) 6/10/93
*/
/*
* Ethernet address - 6 octets
* this is only used by the ethers(3) functions.
*/
struct ether_addr {
u_int8_t ether_addr_octet[6];
};
/*
* Structure of a 10Mb/s Ethernet header.
*/
#define ETHER_ADDR_LEN 6
struct ether_header {
u_int8_t ether_dhost[ETHER_ADDR_LEN];
u_int8_t ether_shost[ETHER_ADDR_LEN];
u_int16_t ether_type;
};
#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
#define ETHERTYPE_IP 0x0800 /* IP protocol */
#define ETHERTYPE_ARP 0x0806 /* address resolution protocol */
#define ETHERTYPE_REVARP 0x8035 /* reverse addr resolution protocol */
/*
* The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
* (type-ETHERTYPE_TRAIL)*512 bytes of data followed
* by an ETHER type (as given above) and then the (variable-length) header.
*/
#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
#define ETHERTYPE_NTRAILER 16
#define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */
#define ETHERMTU 1500
#define ETHERMIN (60-14)
#ifdef _KERNEL
/*
* Macro to map an IP multicast address to an Ethernet multicast address.
* The high-order 25 bits of the Ethernet address are statically assigned,
* and the low-order 23 bits are taken from the low end of the IP address.
*/
#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \
/* struct in_addr *ipaddr; */ \
/* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \
{ \
(enaddr)[0] = 0x01; \
(enaddr)[1] = 0x00; \
(enaddr)[2] = 0x5e; \
(enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \
(enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \
(enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \
}
#endif
/*
* Ethernet Address Resolution Protocol.
*
* See RFC 826 for protocol description. Structure below is adapted
* to resolving internet addresses. Field names used correspond to
* RFC 826.
*/
struct ether_arp {
struct arphdr ea_hdr; /* fixed-size header */
u_int8_t arp_sha[ETHER_ADDR_LEN]; /* sender hardware address */
u_int8_t arp_spa[4]; /* sender protocol address */
u_int8_t arp_tha[ETHER_ADDR_LEN]; /* target hardware address */
u_int8_t arp_tpa[4]; /* target protocol address */
};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
#define arp_pln ea_hdr.ar_pln
#define arp_op ea_hdr.ar_op
/*
* Structure shared between the ethernet driver modules and
* the address resolution code. For example, each ec_softc or il_softc
* begins with this structure.
*/
struct arpcom {
struct ifnet ac_if; /* network-visible interface */
u_int8_t ac_enaddr[ETHER_ADDR_LEN]; /* ethernet hardware address */
char ac__pad[2]; /* be nice to m68k ports */
LIST_HEAD(, ether_multi) ac_multiaddrs; /* list of ether multicast addrs */
int ac_multicnt; /* length of ac_multiaddrs list */
};
struct llinfo_arp {
LIST_ENTRY(llinfo_arp) la_list;
struct rtentry *la_rt;
struct mbuf *la_hold; /* last packet until resolved/timeout */
long la_asked; /* last time we QUERIED for this addr */
#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
};
struct sockaddr_inarp {
u_int8_t sin_len;
u_int8_t sin_family;
u_int16_t sin_port;
struct in_addr sin_addr;
struct in_addr sin_srcaddr;
u_int16_t sin_tos;
u_int16_t sin_other;
#define SIN_PROXY 1
};
/*
* IP and ethernet specific routing flags
*/
#define RTF_USETRAILERS RTF_PROTO1 /* use trailers */
#define RTF_ANNOUNCE RTF_PROTO2 /* announce new arp entry */
#ifdef _KERNEL
u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN];
u_int8_t ether_ipmulticast_min[ETHER_ADDR_LEN];
u_int8_t ether_ipmulticast_max[ETHER_ADDR_LEN];
struct ifqueue arpintrq;
void arpwhohas(struct arpcom *, struct in_addr *);
void arpintr(void);
int arpresolve(struct arpcom *,
struct rtentry *, struct mbuf *, struct sockaddr *, u_char *);
void arp_ifinit(struct arpcom *, struct ifaddr *);
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
int ether_addmulti(struct ifreq *, struct arpcom *);
int ether_delmulti(struct ifreq *, struct arpcom *);
#endif /* _KERNEL */
/*
* Ethernet multicast address structure. There is one of these for each
* multicast address or range of multicast addresses that we are supposed
* to listen to on a particular interface. They are kept in a linked list,
* rooted in the interface's arpcom structure. (This really has nothing to
* do with ARP, or with the Internet address family, but this appears to be
* the minimally-disrupting place to put it.)
*/
struct ether_multi {
u_int8_t enm_addrlo[ETHER_ADDR_LEN]; /* low or only address of range */
u_int8_t enm_addrhi[ETHER_ADDR_LEN]; /* high or only address of range */
struct arpcom *enm_ac; /* back pointer to arpcom */
u_int enm_refcount; /* no. claims to this addr/range */
LIST_ENTRY(ether_multi) enm_list;
};
/*
* Structure used by macros below to remember position when stepping through
* all of the ether_multi records.
*/
struct ether_multistep {
struct ether_multi *e_enm;
};
/*
* Macro for looking up the ether_multi record for a given range of Ethernet
* multicast addresses connected to a given arpcom structure. If no matching
* record is found, "enm" returns NULL.
*/
#define ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm) \
/* u_int8_t addrlo[ETHER_ADDR_LEN]; */ \
/* u_int8_t addrhi[ETHER_ADDR_LEN]; */ \
/* struct arpcom *ac; */ \
/* struct ether_multi *enm; */ \
{ \
for ((enm) = (ac)->ac_multiaddrs.lh_first; \
(enm) != NULL && \
(bcmp((enm)->enm_addrlo, (addrlo), ETHER_ADDR_LEN) != 0 || \
bcmp((enm)->enm_addrhi, (addrhi), ETHER_ADDR_LEN) != 0); \
(enm) = (enm)->enm_list.le_next); \
}
/*
* Macro to step through all of the ether_multi records, one at a time.
* The current position is remembered in "step", which the caller must
* provide. ETHER_FIRST_MULTI(), below, must be called to initialize "step"
* and get the first record. Both macros return a NULL "enm" when there
* are no remaining records.
*/
#define ETHER_NEXT_MULTI(step, enm) \
/* struct ether_multistep step; */ \
/* struct ether_multi *enm; */ \
{ \
if (((enm) = (step).e_enm) != NULL) \
(step).e_enm = (enm)->enm_list.le_next; \
}
#define ETHER_FIRST_MULTI(step, ac, enm) \
/* struct ether_multistep step; */ \
/* struct arpcom *ac; */ \
/* struct ether_multi *enm; */ \
{ \
(step).e_enm = (ac)->ac_multiaddrs.lh_first; \
ETHER_NEXT_MULTI((step), (enm)); \
}
#ifdef _KERNEL
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
int arpresolve(struct arpcom *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *);
void arpintr(void);
int arpioctl(u_long, caddr_t);
void arp_ifinit(struct arpcom *, struct ifaddr *);
void revarpinput(struct mbuf *);
void in_revarpinput(struct mbuf *);
void revarprequest(struct ifnet *);
int revarpwhoarewe(struct ifnet *, struct in_addr *, struct in_addr *);
int revarpwhoami(struct in_addr *, struct ifnet *);
int db_show_arptab(void);
#endif
/*
* Prototype ethers(3) functions.
*/
#ifndef _KERNEL
#include <sys/cdefs.h>
__BEGIN_DECLS
char * ether_ntoa(struct ether_addr *);
struct ether_addr *
ether_aton(char *);
int ether_ntohost(char *, struct ether_addr *);
int ether_hostton(char *, struct ether_addr *);
int ether_line(char *, struct ether_addr *, char *);
__END_DECLS
#endif

83
lib/libstand/in_cksum.c Normal file
View File

@ -0,0 +1,83 @@
/* $NetBSD: in_cksum.c,v 1.3 1995/04/22 13:53:48 cgd Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: in_cksum.c,v 1.1 92/09/11 01:15:55 leres Exp (LBL)
*/
#include <sys/types.h>
/*
* Checksum routine for Internet Protocol family headers.
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
* In particular, it should not be this one.
*/
int
in_cksum(p, len)
register void *p;
register int len;
{
register int sum = 0, oddbyte = 0, v = 0;
register u_char *cp = p;
/* we assume < 2^16 bytes being summed */
while (len > 0) {
if (oddbyte) {
sum += v + *cp++;
len--;
}
if (((long)cp & 1) == 0) {
while ((len -= 2) >= 0) {
sum += *(u_short *)cp;
cp += 2;
}
} else {
while ((len -= 2) >= 0) {
sum += *cp++ << 8;
sum += *cp++;
}
}
if ((oddbyte = len & 1) != 0)
v = *cp << 8;
}
if (oddbyte)
sum += v;
sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
sum += sum >> 16; /* add potential last carry */
return (0xffff & ~sum);
}

89
lib/libstand/ioctl.c Normal file
View File

@ -0,0 +1,89 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
int
ioctl(fd, cmd, arg)
int fd;
u_long cmd;
char *arg;
{
register struct open_file *f = &files[fd];
if ((unsigned)fd >= SOPEN_MAX || 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);
}

54
lib/libstand/iodesc.h Normal file
View File

@ -0,0 +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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*/
#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;
};
#endif /* __SYS_LIBNETBOOT_IODESC_H */

456
lib/libstand/libstand.3 Normal file
View File

@ -0,0 +1,456 @@
.\" Copyright (c) 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 Ohttp://wafu.netgate.net/tama/unix/indexe.htmlTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $Id$
.\"
.Dd June 22, 1998
.Dt LIBSTAND 3
.Os FreeBSD 3.0
.Sh NAME
.Nm libstand
.Nd support library for standalone executables
.Sh SYNOPSIS
.Fd #include <stand.h>
.Sh DESCRIPTION
.Nm
provides a set of supporting functions for standalone
applications, mimicking where possible the standard BSD programming
environment. The following sections group these functions by kind.
Unless specifically described here, see the corresponding section 3
manpages for the given functions.
.Sh STRING FUNCTIONS
String functions are available as documented in
.Xr string 3
and
.Xr bstring 3 .
.Sh MEMORY ALLOCATION
.Bl -hang -width 10n
.It Fn "void *malloc" "size_t size"
.Pp
Allocate
.Fa size
bytes of memory from the heap using a best-fit algorithm.
.It Fn "void free" "void *ptr"
.Pp
Free the allocated object at
.Fa ptr .
.It Fn "void setheap" "void *start" "void *limit"
.Pp
Initialise the heap. This function must be called before calling
.Fn alloc
for the first time. The region between
.Fa start
and
.Fa limit
will be used for the heap; attempting to allocate beyond this will result
in a panic.
.It Fn "char *sbrk" "int junk"
.Pp
Provides the behaviour of
.Fn sbrk 0 ,
ie. returns the highest point that the heap has reached. This value can
be used during testing to determine the actual heap usage. The
.Fa junk
argument is ignored.
.El
.Sh ENVIRONMENT
A set of functions are provided for manipulating a flat variable space similar
to the traditional shell-supported evironment. Major enhancements are support
for set/unset hook functions.
.Bl -hang -width 10n
.It Fn "char *getenv" "const char *name"
.It Fn "int setenv" "const char *name" "char *value" "int overwrite"
.It Fn "int putenv" "const char *string"
.It Fn "int unsetenv" "const char *name"
.Pp
These functions behave similarly to their standard library counterparts.
.It Fn "struct env_var *env_getenv" "const char *name"
.Pp
Looks up a variable in the environment and returns its entire
data structure.
.It Fn "int env_setenv" "const char *name" "int flags" "char *value" "ev_sethook_t sethook" "ev_unsethook_t unsethook"
.Pp
Creates a new or sets an existing environment variable called
.Fa name .
If creating a new variable, the
.Fa sethook
and
.Fa unsethook
arguments may be specified.
.Pp
The set hook is invoked whenever an attempt
is made to set the variable, unless the EV_NOHOOK flag is set. Typically
a set hook will validate the
.Fa value
argument, and then call
.Fn env_setenv
again with EV_NOHOOK set to actually save the value. The predefined function
.Fn env_noset
may be specified to refuse all attempts to set a variable.
.Pp
The unset hook is invoked when an attempt is made to unset a variable. If it
returns zero, the variable will be unset. The predefined function
.Fa env_nounset
may be used to prevent a variable being unset.
.El
.Sh STANDARD LIBRARY SUPPORT
.Bl -hang -width 10n
.It Fn "int getopt" "int argc" "char * const *argv" "cont char *optstring"
.It Fn "long strtol" "const char *nptr" "char **endptr" "int base"
.It Fn "void srandom" "unsigned long seed"
.It Fn "unsigned long random" "void"
.It Fn "char *strerror" "int error"
.Pp
Returns error messages for the subset of errno values supported by
.Nm No .
.El
.Sh CHARACTER I/O
.Bl -hang -width 10n
.It Fn "void gets" "char *buf"
.Pp
Read characters from the console into
.Fa buf .
All of the standard cautions apply to this function.
.It Fn "void ngets" "char *buf" "size_t size"
.Pp
Read at most
.Fa size
- 1 characters from the console into
.Fa buf .
If
.Fa size
is less than 1, the function's behaviour is as for
.Fn gets .
.It Fn "int fgetstr" "char *buf" "int size" "int fd"
.Pp
Read a line of at most
.Fa size
characters into
.Fa buf .
Line terminating characters are stripped, and the buffer is always nul
terminated. Returns the number of characters in
.Fa buf
if successful, or -1 if a read error occurs.
.It Fn "int printf" "const char *fmt" "..."
.It Fn "void vprintf" "const char *fmt" "va_list ap"
.It Fn "int sprintf" "char *buf" "const char *fmt" "..."
.Pp
The *printf functions implement a subset of the standard
.Fn printf
family functionality and some extensions. The following standard conversions
are supported: c,d,n,o,p,s,u,x. The following modifiers are supported:
+,-,#,*,0,field width,precision,l.
.Pp
The
.Li b
conversion is provided to decode error registers. Its usage is:
.Pp
.Bd -offset indent
printf(
.Qq reg=%b\en ,
regval,
.Qq <base><arg>*
);
.Ed
where <base> is the output expressed as a control character, eg. \e10 gives
octal, \e20 gives hex. Each <arg> is a sequence of characters, the first of
which gives the bit number to be inspected (origin 1) and the next characters
(up to a character less than 32) give the text to be displayed if the bit is set.
Thus
.Pp
.Bd -offset indent
printf(
.Qq reg=%b\en
3
.Qq \e10\e2BITTWO\e1BITONE\en
);
.Ed
would give the output
.Pp
.Bd -offset indent
reg=3<BITTWO,BITONE>
.Ed
.Pp
The
.Li D
conversion provides a hexdump facility, eg.
.Pp
.Bd -offset indent -literal
printf(
.Qq %6D ,
ptr,
.Qq \:
); gives
.Qq XX:XX:XX:XX:XX:XX
.Ed
.Bd -offset indent -literal
printf(
.Qq %*D ,
len,
ptr,
.Qq "\ "
); gives
.Qq XX XX XX ...
.Ed
.El
.Sh CHARACTER TESTS AND CONVERSIONS
.Bl -hang -width 10n
.It Fn "int isupper" "int c"
.It Fn "int islower" "int c"
.It Fn "int isspace" "int c"
.It Fn "int isdigit" "int c"
.It Fn "int isxdigit" "int c"
.It Fn "int isascii" "int c"
.It Fn "int isalpha" "int c"
.It Fn "int toupper" "int c"
.It Fn "int tolower" "int c"
.El
.Sh FILE I/O
.Bl -hang -width 10n
.It Fn "int open" "const char *path" "int flags"
.Pp
Similar to the behaviour as specified in
.Xr open 2 ,
except that file creation is not supported, so the mode parameter is not
required. The
.Fa flags
argument may be one of O_RDONLY, O_WRONLY and O_RDWR (although no filesystems
currently support writing).
.It Fn "int close" "int fd"
.It Fn "void closeall" "void"
.Pp
Close all open files.
.It Fn "ssize_t read" "int fd" "void *buf" "size_t len"
.It Fn "ssize_t write" "int fd" "void *buf" "size_t len"
.Pp
(No filesystems currently support writing.)
.It Fn "off_t lseek" "int fd" "off_t offset" "int whence"
.Pp
Files being automatically uncompressed during reading cannot seek backwards
from the current point.
.It Fn "int stat" "const char *path" "struct stat *sb"
.It Fn "int fstat" "int fd" "struct stat *sb"
.Pp
The
.Fn stat
and
.Fn fstat
functions only fill out the following fields in the
.Fa sb
structure: st_mode,st_nlink,st_uid,st_gid,st_size. The
.Nm tftp
filesystem cannot provide meaningful values for this call, and the
.Nm cd9660
filesystem always reports files having uid/gid of zero.
.El
.Sh PAGER
.Nm
supplies a simple internal pager to ease reading the output of large commands.
.Bl -hang -width 10n
.It Fn "void pager_open"
.Pp
Initialises the pager and tells it that the next line output will be the top of the
display. The environment variable LINES is consulted to determine the number of
lines to be displayed before pausing.
.It Fn "void pager_close" "void"
.Pp
Closes the pager.
.It Fn "void pager_output" "char *lines"
.Pp
Sends the lines in the nul-terminated buffer at
.Fa lines
to the pager. Newline characters are counted in order to determine the number
of lines being output (wrapped lines are not accounted for).
.Fn pager_output
will return zero when all of the lines have been output, or nonzero if the
display was paused and the user elected to quit.
.It Fn "int pager_file" "char *fname"
.Pp
Attempts to open and display the file
.Fa fname.
Returns -1 on error, 0 at EOF, or 1 if the user elects to quit while reading.
.El
.Sh MISC
.Bl -hang -width 10n
.It Fn "void twiddle" "void"
.Pp
Successive calls emit the characters in the sequence |,/,-,\\ followed by a
backspace in order to provide reassurance to the user.
.El
.Sh REQUIRED LOW-LEVEL SUPPORT
The following resources are consumed by
.Nm
- stack, heap, console and devices.
.Pp
The stack must be established before
.Nm
functions can be invoked. Stack requirements vary depending on the functions
and filesystems used by the consumer and the support layer functions detailed
below.
.Pp
The heap must be established before calling
.Fn alloc
or
.Fn open
by calling
.Fn setheap .
Heap usage will vary depending on the number of simultaneously open files,
as well as client behaviour. Automatic decompression will allocate more
than 64K of data per open file.
.Pp
Console access is performed via the
.Fn getchar ,
.Fn putchar
and
.Fn ischar
functions detailed below.
.Pp
Device access is initiated via
.Fn devopen
and is performed through the
.Fn dv_strategy ,
.Fn dv_ioctl
and
.Fn dv_close
functions in the device switch structure that
.Fn devopen
returns.
.Pp
The consumer must provide the following support functions:
.Bl -hang -width 10n
.It Fn "int getchar" "void"
.Pp
Return a character from the console, used by
.Fn gets ,
.Fn ngets
and pager functions.
.It Fn "int ischar" "void"
.Pp
Returns nonzero if a character is waiting from the console.
.It Fn "void putchar" "int"
.Pp
Write a character to the console, used by
.Fn gets ,
.Fn ngets ,
.Fn *printf ,
.Fn panic
and
.Fn twiddle
and thus by many other functions for debugging and informational output.
.It Fn "int devopen" "struct open_file *of" "const char *name" "char **file"
.Pp
Open the appropriate device for the file named in
.Fa name ,
returning in
.Fa file
a pointer to the remaining body of
.Fa name
which does not refer to the device. The
.Va f_dev
field in
.Fa of
will be set to point to the
.Dv devsw
structure for the opened device if successful. Device identifiers must
always precede the path component, but may otherwise be arbitrarily formatted.
Used by
.Fn open
and thus for all device-related I/O.
.It Fn "int devclose" "struct open_file *of"
Close the device allocated for
.Fa of .
The device driver itself will already have been called for the close; this call
should clean up any allocation made by devopen only.
.It Fn "void panic" "const char *msg" "..."
.Pp
Signal a fatal and unrecoverable error condition. The
.Fa msg ...
arguments are as for
.Fn printf .
.El
.Sh INTERNAL FILESYSTEMS
Internal filesystems are enabled by the consumer exporting the array
.Dv struct fs_ops *file_system[], which should be initialised with pointers
to
.Dv struct fs_ops
structures. The following filesystem handlers are supplied by
.Nm No ,
the consumer may supply other filesystems of their own:
.Bl -hang -width "cd9660_fsops "
.It ufs_fsops
The BSD UFS.
.It tftp_fsops
File access via TFTP.
.It nfs_fsops
File access via NFS.
.It cd9660_fsops
ISO 9660 (CD-ROM) filesystem.
.It zipfs_fsops
Stacked filesystem supporting gzipped files. When trying the zipfs filesystem,
.Nm
appends
.Li .gz
to the end of the filename, and then tries to locate the file using the other
filesystems. Placement of this filesystem in the
.Dv file_system[]
array determines whether gzipped files will be opened in preference to non-gzipped
files. It is only possible to seek a gzipped file forwards, and
.Fn stat
and
.Fn fstat
on gzipped files will report an invalid length.
.El
.Pp
The array of
.Dv struct fs_ops
pointers should be terminated with a NULL.
.Sh DEVICES
Devices are exported by the supporting code via the array
.Dv struct devsw *devsw[]
which is a NULL terminated array of pointers to device switch structures.
.Sh BUGS
.Pp
The lack of detailed memory usage data is unhelpful.
.Sh HISTORY
.Nm
contains contributions from many sources, including:
.Bl -bullet -compact
.It
.Nm libsa
from
.Nx
.It
.Nm libc
and
.Nm libkern
from
.Fx 3.0 .
.El
.Pp
The reorganisation and port to
.Fx 3.0 ,
the environment functions and this manpage were written by
.An Mike Smith Aq msmith@freebsd.org .

102
lib/libstand/lseek.c Normal file
View File

@ -0,0 +1,102 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
off_t
lseek(fd, offset, where)
int fd;
off_t offset;
int where;
{
register struct open_file *f = &files[fd];
if ((unsigned)fd >= SOPEN_MAX || 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;
case SEEK_END:
default:
errno = EOFFSET;
return (-1);
}
return (f->f_offset);
}
return (f->f_ops->fo_seek)(f, offset, where);
}

503
lib/libstand/net.c Normal file
View File

@ -0,0 +1,503 @@
/* $NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL)
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <string.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include "stand.h"
#include "net.h"
/* Caller must leave room for ethernet, ip and udp headers in front!! */
ssize_t
sendudp(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register size_t len;
{
register ssize_t cc;
register struct ip *ip;
register struct udphdr *uh;
register u_char *ea;
#ifdef NET_DEBUG
if (debug) {
printf("sendudp: d=%lx called.\n", (long)d);
if (d) {
printf("saddr: %s:%d",
inet_ntoa(d->myip), ntohs(d->myport));
printf(" daddr: %s:%d\n",
inet_ntoa(d->destip), ntohs(d->destport));
}
}
#endif
uh = (struct udphdr *)pkt - 1;
ip = (struct ip *)uh - 1;
len += sizeof(*ip) + sizeof(*uh);
bzero(ip, sizeof(*ip) + sizeof(*uh));
ip->ip_v = IPVERSION; /* half-char */
ip->ip_hl = sizeof(*ip) >> 2; /* half-char */
ip->ip_len = htons(len);
ip->ip_p = IPPROTO_UDP; /* char */
ip->ip_ttl = IP_TTL; /* char */
ip->ip_src = d->myip;
ip->ip_dst = d->destip;
ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */
uh->uh_sport = d->myport;
uh->uh_dport = d->destport;
uh->uh_ulen = htons(len - sizeof(*ip));
#ifndef UDP_NO_CKSUM
{
register struct udpiphdr *ui;
struct ip tip;
/* Calculate checksum (must save and restore ip header) */
tip = *ip;
ui = (struct udpiphdr *)ip;
bzero(&ui->ui_x1, sizeof(ui->ui_x1));
ui->ui_len = uh->uh_ulen;
uh->uh_sum = in_cksum(ui, len);
*ip = tip;
}
#endif
if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 ||
netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask))
ea = arpwhohas(d, ip->ip_dst);
else
ea = arpwhohas(d, gateip);
cc = sendether(d, ip, len, ea, ETHERTYPE_IP);
if (cc == -1)
return (-1);
if (cc != len)
panic("sendudp: bad write (%d != %d)", cc, len);
return (cc - (sizeof(*ip) + sizeof(*uh)));
}
/*
* Receive a UDP packet and validate it is for us.
* Caller leaves room for the headers (Ether, IP, UDP)
*/
ssize_t
readudp(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
{
register ssize_t n;
register size_t hlen;
register struct ip *ip;
register struct udphdr *uh;
u_int16_t etype; /* host order */
#ifdef NET_DEBUG
if (debug)
printf("readudp: called\n");
#endif
uh = (struct udphdr *)pkt - 1;
ip = (struct ip *)uh - 1;
n = readether(d, ip, len + sizeof(*ip) + sizeof(*uh), tleft, &etype);
if (n == -1 || n < sizeof(*ip) + sizeof(*uh))
return -1;
/* Ethernet address checks now in readether() */
/* Need to respond to ARP requests. */
if (etype == ETHERTYPE_ARP) {
struct arphdr *ah = (void *)ip;
if (ah->ar_op == htons(ARPOP_REQUEST)) {
/* Send ARP reply */
arp_reply(d, ah);
}
return -1;
}
if (etype != ETHERTYPE_IP) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: not IP. ether_type=%x\n", etype);
#endif
return -1;
}
/* Check ip header */
if (ip->ip_v != IPVERSION ||
ip->ip_p != IPPROTO_UDP) { /* half char */
#ifdef NET_DEBUG
if (debug)
printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p);
#endif
return -1;
}
hlen = ip->ip_hl << 2;
if (hlen < sizeof(*ip) ||
in_cksum(ip, hlen) != 0) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: short hdr or bad cksum.\n");
#endif
return -1;
}
if (n < ntohs(ip->ip_len)) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: bad length %d < %d.\n",
(int)n, ntohs(ip->ip_len));
#endif
return -1;
}
if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) {
#ifdef NET_DEBUG
if (debug) {
printf("readudp: bad saddr %s != ", inet_ntoa(d->myip));
printf("%s\n", inet_ntoa(ip->ip_dst));
}
#endif
return -1;
}
/* If there were ip options, make them go away */
if (hlen != sizeof(*ip)) {
bcopy(((u_char *)ip) + hlen, uh, len - hlen);
ip->ip_len = htons(sizeof(*ip));
n -= hlen - sizeof(*ip);
}
if (uh->uh_dport != d->myport) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: bad dport %d != %d\n",
d->myport, ntohs(uh->uh_dport));
#endif
return -1;
}
#ifndef UDP_NO_CKSUM
if (uh->uh_sum) {
register struct udpiphdr *ui;
struct ip tip;
n = ntohs(uh->uh_ulen) + sizeof(*ip);
if (n > RECV_SIZE - ETHER_SIZE) {
printf("readudp: huge packet, udp len %d\n", (int)n);
return -1;
}
/* Check checksum (must save and restore ip header) */
tip = *ip;
ui = (struct udpiphdr *)ip;
bzero(&ui->ui_x1, sizeof(ui->ui_x1));
ui->ui_len = uh->uh_ulen;
if (in_cksum(ui, n) != 0) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: bad cksum\n");
#endif
*ip = tip;
return -1;
}
*ip = tip;
}
#endif
if (ntohs(uh->uh_ulen) < sizeof(*uh)) {
#ifdef NET_DEBUG
if (debug)
printf("readudp: bad udp len %d < %d\n",
ntohs(uh->uh_ulen), (int)sizeof(*uh));
#endif
return -1;
}
n -= sizeof(*ip) + sizeof(*uh);
return (n);
}
/*
* Send a packet and wait for a reply, with exponential backoff.
*
* The send routine must return the actual number of bytes written,
* or -1 on error.
*
* The receive routine can indicate success by returning the number of
* bytes read; it can return 0 to indicate EOF; it can return -1 with a
* non-zero errno to indicate failure; finally, it can return -1 with a
* zero errno to indicate it isn't done yet.
*/
ssize_t
sendrecv(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
register struct iodesc *d;
register ssize_t (*sproc)(struct iodesc *, void *, size_t);
register void *sbuf;
register size_t ssize;
register ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t);
register void *rbuf;
register size_t rsize;
{
register ssize_t cc;
register time_t t, tmo, tlast;
long tleft;
#ifdef NET_DEBUG
if (debug)
printf("sendrecv: called\n");
#endif
tmo = MINTMO;
tlast = tleft = 0;
t = getsecs();
for (;;) {
if (tleft <= 0) {
if (tmo >= MAXTMO) {
errno = ETIMEDOUT;
return -1;
}
cc = (*sproc)(d, sbuf, ssize);
if (cc != -1 && cc < ssize)
panic("sendrecv: short write! (%d < %d)",
cc, ssize);
tleft = tmo;
tmo <<= 1;
if (tmo > MAXTMO)
tmo = MAXTMO;
if (cc == -1) {
/* Error on transmit; wait before retrying */
while ((getsecs() - t) < tmo);
tleft = 0;
continue;
}
tlast = t;
}
/* Try to get a packet and process it. */
cc = (*rproc)(d, rbuf, rsize, tleft);
/* Return on data, EOF or real error. */
if (cc != -1 || errno != 0)
return (cc);
/* Timed out or didn't get the packet we're waiting for */
t = getsecs();
tleft -= t - tlast;
tlast = t;
}
}
/*
* Like inet_addr() in the C library, but we only accept base-10.
* Return values are in network order.
*/
n_long
inet_addr(cp)
char *cp;
{
register u_long val;
register int n;
register char c;
u_int parts[4];
register u_int *pp = parts;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, other=decimal.
*/
val = 0;
while ((c = *cp) != '\0') {
if (c >= '0' && c <= '9') {
val = (val * 10) + (c - '0');
cp++;
continue;
}
break;
}
if (*cp == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16-bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3 || val > 0xff)
goto bad;
*pp++ = val, cp++;
} else
break;
}
/*
* Check for trailing characters.
*/
if (*cp != '\0')
goto bad;
/*
* Concoct the address according to
* the number of parts specified.
*/
n = pp - parts + 1;
switch (n) {
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
goto bad;
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
goto bad;
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
goto bad;
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
return (htonl(val));
bad:
return (htonl(INADDR_NONE));
}
char *
inet_ntoa(ia)
struct in_addr ia;
{
return (intoa(ia.s_addr));
}
/* Similar to inet_ntoa() */
char *
intoa(addr)
register n_long addr;
{
register char *cp;
register u_int byte;
register int n;
static char buf[17]; /* strlen(".255.255.255.255") + 1 */
NTOHL(addr);
cp = &buf[sizeof buf];
*--cp = '\0';
n = 4;
do {
byte = addr & 0xff;
*--cp = byte % 10 + '0';
byte /= 10;
if (byte > 0) {
*--cp = byte % 10 + '0';
byte /= 10;
if (byte > 0)
*--cp = byte + '0';
}
*--cp = '.';
addr >>= 8;
} while (--n > 0);
return (cp+1);
}
static char *
number(s, n)
char *s;
int *n;
{
for (*n = 0; isdigit(*s); s++)
*n = (*n * 10) + *s - '0';
return s;
}
n_long
ip_convertaddr(p)
char *p;
{
#define IP_ANYADDR 0
n_long addr = 0, n;
if (p == (char *)0 || *p == '\0')
return IP_ANYADDR;
p = number(p, &n);
addr |= (n << 24) & 0xff000000;
if (*p == '\0' || *p++ != '.')
return IP_ANYADDR;
p = number(p, &n);
addr |= (n << 16) & 0xff0000;
if (*p == '\0' || *p++ != '.')
return IP_ANYADDR;
p = number(p, &n);
addr |= (n << 8) & 0xff00;
if (*p == '\0' || *p++ != '.')
return IP_ANYADDR;
p = number(p, &n);
addr |= n & 0xff;
if (*p != '\0')
return IP_ANYADDR;
return htonl(addr);
}

122
lib/libstand/net.h Normal file
View File

@ -0,0 +1,122 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*/
#define NETIF_DEBUG 1
#ifndef _KERNEL /* XXX - see <netinet/in.h> */
#undef __IPADDR
#define __IPADDR(x) htonl((u_int32_t)(x))
#endif
#include "iodesc.h"
#define BA { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
/* 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 20 /* 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 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 n_long netmask;
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 *d, void *pkt, size_t len,
time_t tleft, u_int16_t *etype);
ssize_t sendudp(struct iodesc *, void *, size_t);
ssize_t readudp(struct iodesc *, void *, size_t, time_t);
ssize_t sendrecv(struct iodesc *,
ssize_t (*)(struct iodesc *, void *, size_t),
void *, size_t,
ssize_t (*)(struct iodesc *, void *, size_t, time_t),
void *, size_t);
/* 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 *);
/* Machine-dependent functions: */
time_t getsecs(void);

332
lib/libstand/netif.c Normal file
View File

@ -0,0 +1,332 @@
/* $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 <sys/param.h>
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/mount.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
struct iodesc sockets[SOPEN_MAX];
#ifdef NETIF_DEBUG
int netif_debug = 0;
#endif
/*
* netif_init:
*
* initialize the generic network interface layer
*/
void
netif_init()
{
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(nif, machdep_hint)
struct netif *nif;
void *machdep_hint;
{
struct netif_driver *drv = nif->nif_driver;
#if 0
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(machdep_hint)
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(nif, machdep_hint)
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(nif, desc, machdep_hint)
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;
#ifdef PARANOID
if (drv->netif_init == NULL)
panic("%s%d: no netif_init support\n", drv->netif_bname,
nif->nif_unit);
#endif
drv->netif_init(desc, machdep_hint);
bzero(drv->netif_ifs[nif->nif_unit].dif_stats,
sizeof(struct netif_stats));
}
void
netif_detach(nif)
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\n", drv->netif_bname,
nif->nif_unit);
#endif
drv->netif_end(nif);
}
ssize_t
netif_get(desc, pkt, len, timo)
struct iodesc *desc;
void *pkt;
size_t len;
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\n", drv->netif_bname,
nif->nif_unit);
#endif
rv = drv->netif_get(desc, pkt, len, 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(desc, pkt, len)
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\n", 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;
}
struct iodesc *
socktodesc(sock)
int sock;
{
if (sock >= SOPEN_MAX) {
errno = EBADF;
return (NULL);
}
return (&sockets[sock]);
}
int
netif_open(machdep_hint)
void *machdep_hint;
{
int fd;
register 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));
netif_init();
nif = netif_select(machdep_hint);
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);
}
int
netif_close(sock)
int sock;
{
if (sock >= SOPEN_MAX) {
errno = EBADF;
return(-1);
}
netif_detach(sockets[sock].io_netif);
sockets[sock].io_netif = (struct netif *)0;
return(0);
}

65
lib/libstand/netif.h Normal file
View File

@ -0,0 +1,65 @@
/* $NetBSD: netif.h,v 1.4 1995/09/14 23:45:30 pk Exp $ */
#ifndef __SYS_LIBNETBOOT_NETIF_H
#define __SYS_LIBNETBOOT_NETIF_H
#include "iodesc.h"
#define NENTS(x) sizeof(x)/sizeof(x[0])
struct netif_driver {
char *netif_bname;
int (*netif_match)(struct netif *, void *);
int (*netif_probe)(struct netif *, void *);
void (*netif_init)(struct iodesc *, void *);
int (*netif_get)(struct iodesc *, void *, size_t, time_t);
int (*netif_put)(struct iodesc *, void *, size_t);
void (*netif_end)(struct netif *);
struct netif_dif *netif_ifs;
int netif_nifs;
};
struct netif_dif {
int dif_unit;
int dif_nsel;
struct netif_stats *dif_stats;
void *dif_private;
/* the following fields are used internally by the netif layer */
u_long dif_used;
};
struct netif_stats {
int collisions;
int collision_error;
int missed;
int sent;
int received;
int deferred;
int overflow;
};
struct netif {
struct netif_driver *nif_driver;
int nif_unit;
int nif_sel;
void *nif_devdata;
};
extern struct netif_driver *netif_drivers[]; /* machdep */
extern int n_netif_drivers;
extern int netif_debug;
void netif_init(void);
struct netif *netif_select(void *);
int netif_probe(struct netif *, void *);
void netif_attach(struct netif *, struct iodesc *, void *);
void netif_detach(struct netif *);
ssize_t netif_get(struct iodesc *, void *, size_t, time_t);
ssize_t netif_put(struct iodesc *, void *, size_t);
int netif_open(void *);
int netif_close(int);
struct iodesc *socktodesc(int);
#endif /* __SYS_LIBNETBOOT_NETIF_H */

653
lib/libstand/nfs.c Normal file
View File

@ -0,0 +1,653 @@
/* $NetBSD: nfs.c,v 1.2 1998/01/24 12:43:09 drochner Exp $ */
/*-
* Copyright (c) 1993 John Brezak
* 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. 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 THE AUTHOR `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 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 <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <string.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include "rpcv2.h"
#include "nfsv2.h"
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "nfs.h"
#include "rpc.h"
#define NFS_DEBUGxx
/* Define our own NFS attributes without NQNFS stuff. */
struct nfsv2_fattrs {
n_long fa_type;
n_long fa_mode;
n_long fa_nlink;
n_long fa_uid;
n_long fa_gid;
n_long fa_size;
n_long fa_blocksize;
n_long fa_rdev;
n_long fa_blocks;
n_long fa_fsid;
n_long fa_fileid;
struct nfsv2_time fa_atime;
struct nfsv2_time fa_mtime;
struct nfsv2_time fa_ctime;
};
struct nfs_read_args {
u_char fh[NFS_FHSIZE];
n_long off;
n_long len;
n_long xxx; /* XXX what's this for? */
};
/* Data part of nfs rpc reply (also the largest thing we receive) */
#define NFSREAD_SIZE 1024
struct nfs_read_repl {
n_long errno;
struct nfsv2_fattrs fa;
n_long count;
u_char data[NFSREAD_SIZE];
};
#ifndef NFS_NOSYMLINK
struct nfs_readlnk_repl {
n_long errno;
n_long len;
char path[NFS_MAXPATHLEN];
};
#endif
struct nfs_iodesc {
struct iodesc *iodesc;
off_t off;
u_char fh[NFS_FHSIZE];
struct nfsv2_fattrs fa; /* all in network order */
};
/*
* XXX interactions with tftp? See nfswrapper.c for a confusing
* issue.
*/
int nfs_open(char *path, struct open_file *f);
static int nfs_close(struct open_file *f);
static int nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static int nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t nfs_seek(struct open_file *f, off_t offset, int where);
static int nfs_stat(struct open_file *f, struct stat *sb);
struct fs_ops nfs_fsops = {
"nfs", nfs_open, nfs_close, nfs_read, nfs_write, nfs_seek, nfs_stat
};
/*
* Fetch the root file handle (call mount daemon)
* Return zero or error number.
*/
int
nfs_getrootfh(d, path, fhp)
register struct iodesc *d;
char *path;
u_char *fhp;
{
register int len;
struct args {
n_long len;
char path[FNAME_SIZE];
} *args;
struct repl {
n_long errno;
u_char fh[NFS_FHSIZE];
} *repl;
struct {
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct repl d;
} rdata;
size_t cc;
#ifdef NFS_DEBUG
if (debug)
printf("nfs_getrootfh: %s\n", path);
#endif
args = &sdata.d;
repl = &rdata.d;
bzero(args, sizeof(*args));
len = strlen(path);
if (len > sizeof(args->path))
len = sizeof(args->path);
args->len = htonl(len);
bcopy(path, args->path, len);
len = 4 + roundup(len, 4);
cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
args, len, repl, sizeof(*repl));
if (cc == -1) {
/* errno was set by rpc_call */
return (errno);
}
if (cc < 4)
return (EBADRPC);
if (repl->errno)
return (ntohl(repl->errno));
bcopy(repl->fh, fhp, sizeof(repl->fh));
return (0);
}
/*
* Lookup a file. Store handle and attributes.
* Return zero or error number.
*/
int
nfs_lookupfh(d, name, newfd)
struct nfs_iodesc *d;
char *name;
struct nfs_iodesc *newfd;
{
register int len, rlen;
struct args {
u_char fh[NFS_FHSIZE];
n_long len;
char name[FNAME_SIZE];
} *args;
struct repl {
n_long errno;
u_char fh[NFS_FHSIZE];
struct nfsv2_fattrs fa;
} *repl;
struct {
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct repl d;
} rdata;
ssize_t cc;
#ifdef NFS_DEBUG
if (debug)
printf("lookupfh: called\n");
#endif
args = &sdata.d;
repl = &rdata.d;
bzero(args, sizeof(*args));
bcopy(d->fh, args->fh, sizeof(args->fh));
len = strlen(name);
if (len > sizeof(args->name))
len = sizeof(args->name);
bcopy(name, args->name, len);
args->len = htonl(len);
len = 4 + roundup(len, 4);
len += NFS_FHSIZE;
rlen = sizeof(*repl);
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
args, len, repl, rlen);
if (cc == -1)
return (errno); /* XXX - from rpc_call */
if (cc < 4)
return (EIO);
if (repl->errno) {
/* saerrno.h now matches NFS error numbers. */
return (ntohl(repl->errno));
}
bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
return (0);
}
#ifndef NFS_NOSYMLINK
/*
* Get the destination of a symbolic link.
*/
int
nfs_readlink(d, buf)
struct nfs_iodesc *d;
char *buf;
{
struct {
n_long h[RPC_HEADER_WORDS];
u_char fh[NFS_FHSIZE];
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct nfs_readlnk_repl d;
} rdata;
ssize_t cc;
#ifdef NFS_DEBUG
if (debug)
printf("readlink: called\n");
#endif
bcopy(d->fh, sdata.fh, NFS_FHSIZE);
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
sdata.fh, NFS_FHSIZE,
&rdata.d, sizeof(rdata.d));
if (cc == -1)
return (errno);
if (cc < 4)
return (EIO);
if (rdata.d.errno)
return (ntohl(rdata.d.errno));
rdata.d.len = ntohl(rdata.d.len);
if (rdata.d.len > NFS_MAXPATHLEN)
return (ENAMETOOLONG);
bcopy(rdata.d.path, buf, rdata.d.len);
buf[rdata.d.len] = 0;
return (0);
}
#endif
/*
* Read data from a file.
* Return transfer count or -1 (and set errno)
*/
ssize_t
nfs_readdata(d, off, addr, len)
struct nfs_iodesc *d;
off_t off;
void *addr;
size_t len;
{
struct nfs_read_args *args;
struct nfs_read_repl *repl;
struct {
n_long h[RPC_HEADER_WORDS];
struct nfs_read_args d;
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct nfs_read_repl d;
} rdata;
size_t cc;
long x;
int hlen, rlen;
args = &sdata.d;
repl = &rdata.d;
bcopy(d->fh, args->fh, NFS_FHSIZE);
args->off = htonl((n_long)off);
if (len > NFSREAD_SIZE)
len = NFSREAD_SIZE;
args->len = htonl((n_long)len);
args->xxx = htonl((n_long)0);
hlen = sizeof(*repl) - NFSREAD_SIZE;
cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
args, sizeof(*args),
repl, sizeof(*repl));
if (cc == -1) {
/* errno was already set by rpc_call */
return (-1);
}
if (cc < hlen) {
errno = EBADRPC;
return (-1);
}
if (repl->errno) {
errno = ntohl(repl->errno);
return (-1);
}
rlen = cc - hlen;
x = ntohl(repl->count);
if (rlen < x) {
printf("nfsread: short packet, %d < %ld\n", rlen, x);
errno = EBADRPC;
return(-1);
}
bcopy(repl->data, addr, x);
return (x);
}
/*
* Open a file.
* return zero or error number
*/
int
nfs_open(path, f)
char *path;
struct open_file *f;
{
static struct nfs_iodesc nfs_root_node;
struct iodesc *desc;
struct nfs_iodesc *currfd;
#ifndef NFS_NOSYMLINK
struct nfs_iodesc *newfd;
struct nfsv2_fattrs *fa;
register char *cp, *ncp;
register int c;
char namebuf[NFS_MAXPATHLEN + 1];
char linkbuf[NFS_MAXPATHLEN + 1];
int nlinks = 0;
#endif
int error;
#ifdef NFS_DEBUG
if (debug)
printf("nfs_open: %s (rootpath=%s)\n", path, rootpath);
#endif
if (!rootpath[0]) {
printf("no rootpath, no nfs\n");
return (ENXIO);
}
if (!(desc = socktodesc(*(int *)(f->f_devdata))))
return(EINVAL);
/* Bind to a reserved port. */
desc->myport = htons(--rpc_port);
desc->destip = rootip;
if ((error = nfs_getrootfh(desc, rootpath, nfs_root_node.fh)))
return (error);
nfs_root_node.iodesc = desc;
#ifndef NFS_NOSYMLINK
/* Fake up attributes for the root dir. */
fa = &nfs_root_node.fa;
fa->fa_type = htonl(NFDIR);
fa->fa_mode = htonl(0755);
fa->fa_nlink = htonl(2);
currfd = &nfs_root_node;
newfd = 0;
cp = path;
while (*cp) {
/*
* Remove extra separators
*/
while (*cp == '/')
cp++;
if (*cp == '\0')
break;
/*
* Check that current node is a directory.
*/
if (currfd->fa.fa_type != htonl(NFDIR)) {
error = ENOTDIR;
goto out;
}
/* allocate file system specific data structure */
newfd = malloc(sizeof(*newfd));
newfd->iodesc = currfd->iodesc;
newfd->off = 0;
/*
* Get next component of path name.
*/
{
register int len = 0;
ncp = cp;
while ((c = *cp) != '\0' && c != '/') {
if (++len > NFS_MAXNAMLEN) {
error = ENOENT;
goto out;
}
cp++;
}
*cp = '\0';
}
/* lookup a file handle */
error = nfs_lookupfh(currfd, ncp, newfd);
*cp = c;
if (error)
goto out;
/*
* Check for symbolic link
*/
if (newfd->fa.fa_type == htonl(NFLNK)) {
int link_len, len;
error = nfs_readlink(newfd, linkbuf);
if (error)
goto out;
link_len = strlen(linkbuf);
len = strlen(cp);
if (link_len + len > MAXPATHLEN
|| ++nlinks > MAXSYMLINKS) {
error = ENOENT;
goto out;
}
bcopy(cp, &namebuf[link_len], len + 1);
bcopy(linkbuf, namebuf, link_len);
/*
* If absolute pathname, restart at root.
* If relative pathname, restart at parent directory.
*/
cp = namebuf;
if (*cp == '/') {
if (currfd != &nfs_root_node)
free(currfd);
currfd = &nfs_root_node;
}
free(newfd);
newfd = 0;
continue;
}
if (currfd != &nfs_root_node)
free(currfd);
currfd = newfd;
newfd = 0;
}
error = 0;
out:
if (newfd)
free(newfd);
#else
/* allocate file system specific data structure */
currfd = malloc(sizeof(*currfd));
currfd->iodesc = desc;
currfd->off = 0;
error = nfs_lookupfh(&nfs_root_node, path, currfd);
#endif
if (!error) {
f->f_fsdata = (void *)currfd;
return (0);
}
#ifdef NFS_DEBUG
if (debug)
printf("nfs_open: %s lookupfh failed: %s\n",
path, strerror(error));
#endif
#ifndef NFS_NOSYMLINK
if (currfd != &nfs_root_node)
#endif
free(currfd);
return (error);
}
int
nfs_close(f)
struct open_file *f;
{
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
#ifdef NFS_DEBUG
if (debug)
printf("nfs_close: fp=0x%lx\n", (u_long)fp);
#endif
if (fp)
free(fp);
f->f_fsdata = (void *)0;
return (0);
}
/*
* read a portion of a file
*/
int
nfs_read(f, buf, size, resid)
struct open_file *f;
void *buf;
size_t size;
size_t *resid; /* out */
{
register struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
register ssize_t cc;
register char *addr = buf;
#ifdef NFS_DEBUG
if (debug)
printf("nfs_read: size=%lu off=%d\n", (u_long)size,
(int)fp->off);
#endif
while ((int)size > 0) {
twiddle();
cc = nfs_readdata(fp, fp->off, (void *)addr, size);
/* XXX maybe should retry on certain errors */
if (cc == -1) {
#ifdef NFS_DEBUG
if (debug)
printf("nfs_read: read: %s", strerror(errno));
#endif
return (errno); /* XXX - from nfs_readdata */
}
if (cc == 0) {
#ifdef NFS_DEBUG
if (debug)
printf("nfs_read: hit EOF unexpectantly");
#endif
goto ret;
}
fp->off += cc;
addr += cc;
size -= cc;
}
ret:
if (resid)
*resid = size;
return (0);
}
/*
* Not implemented.
*/
int
nfs_write(f, buf, size, resid)
struct open_file *f;
void *buf;
size_t size;
size_t *resid; /* out */
{
return (EROFS);
}
off_t
nfs_seek(f, offset, where)
struct open_file *f;
off_t offset;
int where;
{
register struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
n_long size = ntohl(d->fa.fa_size);
switch (where) {
case SEEK_SET:
d->off = offset;
break;
case SEEK_CUR:
d->off += offset;
break;
case SEEK_END:
d->off = size - offset;
break;
default:
return (-1);
}
return (d->off);
}
/* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
int nfs_stat_types[8] = {
0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
int
nfs_stat(f, sb)
struct open_file *f;
struct stat *sb;
{
struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
register n_long ftype, mode;
ftype = ntohl(fp->fa.fa_type);
mode = ntohl(fp->fa.fa_mode);
mode |= nfs_stat_types[ftype & 7];
sb->st_mode = mode;
sb->st_nlink = ntohl(fp->fa.fa_nlink);
sb->st_uid = ntohl(fp->fa.fa_uid);
sb->st_gid = ntohl(fp->fa.fa_gid);
sb->st_size = ntohl(fp->fa.fa_size);
return (0);
}

37
lib/libstand/nfs.h Normal file
View File

@ -0,0 +1,37 @@
/* $NetBSD: nfs.h,v 1.5 1996/07/10 18:32:33 cgd 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
extern int nfs_open(char *path, struct open_file *f); /* XXX for nfswrapper */

166
lib/libstand/nfsv2.h Normal file
View File

@ -0,0 +1,166 @@
/* $NetBSD: nfsv2.h,v 1.2 1996/02/26 23:05:23 gwr Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* 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 the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)nfsv2.h 8.1 (Berkeley) 6/10/93
*/
/*
* nfs definitions as per the version 2 specs
*/
/*
* Constants as defined in the Sun NFS Version 2 spec.
* "NFS: Network File System Protocol Specification" RFC1094
*/
#define NFS_PORT 2049
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_MAXDGRAMDATA 8192
#define NFS_MAXDATA 32768
#define NFS_MAXPATHLEN 1024
#define NFS_MAXNAMLEN 255
#define NFS_FHSIZE 32
#define NFS_MAXPKTHDR 404
#define NFS_MAXPACKET (NFS_MAXPKTHDR+NFS_MAXDATA)
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
/* Stat numbers for rpc returns */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_WFLUSH 99
/* Sizes in bytes of various nfs rpc components */
#define NFSX_FH 32
#define NFSX_UNSIGNED 4
#define NFSX_FATTR 68
#define NFSX_SATTR 32
#define NFSX_STATFS 20
#define NFSX_COOKIE 4
/* nfs rpc procedure numbers */
#define NFSPROC_NULL 0
#define NFSPROC_GETATTR 1
#define NFSPROC_SETATTR 2
#define NFSPROC_NOOP 3
#define NFSPROC_ROOT NFSPROC_NOOP /* Obsolete */
#define NFSPROC_LOOKUP 4
#define NFSPROC_READLINK 5
#define NFSPROC_READ 6
#define NFSPROC_WRITECACHE NFSPROC_NOOP /* Obsolete */
#define NFSPROC_WRITE 8
#define NFSPROC_CREATE 9
#define NFSPROC_REMOVE 10
#define NFSPROC_RENAME 11
#define NFSPROC_LINK 12
#define NFSPROC_SYMLINK 13
#define NFSPROC_MKDIR 14
#define NFSPROC_RMDIR 15
#define NFSPROC_READDIR 16
#define NFSPROC_STATFS 17
#define NFS_NPROCS 18
/* File types */
typedef enum {
NFNON=0,
NFREG=1,
NFDIR=2,
NFBLK=3,
NFCHR=4,
NFLNK=5
} nfstype;
/* Structs for common parts of the rpc's */
struct nfsv2_time {
n_long nfs_sec;
n_long nfs_usec;
};
/*
* File attributes and setable attributes.
*/
struct nfsv2_fattr {
n_long fa_type;
n_long fa_mode;
n_long fa_nlink;
n_long fa_uid;
n_long fa_gid;
n_long fa_size;
n_long fa_blocksize;
n_long fa_rdev;
n_long fa_blocks;
n_long fa_fsid;
n_long fa_fileid;
struct nfsv2_time fa_atime;
struct nfsv2_time fa_mtime;
struct nfsv2_time fa_ctime;
};
struct nfsv2_sattr {
n_long sa_mode;
n_long sa_uid;
n_long sa_gid;
n_long sa_size;
struct nfsv2_time sa_atime;
struct nfsv2_time sa_mtime;
};
struct nfsv2_statfs {
n_long sf_tsize;
n_long sf_bsize;
n_long sf_blocks;
n_long sf_bfree;
n_long sf_bavail;
};

105
lib/libstand/nullfs.c Normal file
View File

@ -0,0 +1,105 @@
/* $NetBSD: nullfs.c,v 1.1 1996/01/13 22:25:39 leo 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
/*
* Null filesystem
*/
int null_open (char *path, struct open_file *f)
{
errno = EIO;
return -1;
}
int null_close(struct open_file *f)
{
return 0;
}
ssize_t null_read (struct open_file *f, void *buf, size_t size, size_t *resid)
{
errno = EIO;
return -1;
}
ssize_t null_write (struct open_file *f, void *buf, size_t size, size_t *resid)
{
errno = EIO;
return -1;
}
off_t null_seek (struct open_file *f, off_t offset, int where)
{
errno = EIO;
return -1;
}
int null_stat (struct open_file *f, struct stat *sb)
{
errno = EIO;
return -1;
}

137
lib/libstand/open.c Normal file
View File

@ -0,0 +1,137 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
struct open_file files[SOPEN_MAX];
static int
o_gethandle(void)
{
int fd;
for (fd = 0; fd < SOPEN_MAX; fd++)
if (files[fd].f_flags == 0)
return(fd);
return(-1);
}
int
open(const char *fname, int mode)
{
struct open_file *f;
int fd, i, error, besterror;
char *file;
if ((fd = o_gethandle()) == -1) {
errno = EMFILE;
return(-1);
}
f = &files[fd];
f->f_flags = mode + 1;
f->f_dev = (struct devsw *)0;
f->f_ops = (struct fs_ops *)0;
f->f_offset = 0;
f->f_devdata = NULL;
file = (char *)0;
error = devopen(f, fname, &file);
if (error ||
(((f->f_flags & F_NODEV) == 0) && f->f_dev == (struct devsw *)0))
goto err;
/* see if we opened a raw device; otherwise, 'file' is the file name. */
if (file == (char *)0 || *file == '\0') {
f->f_flags |= F_RAW;
return (fd);
}
/* pass file name to the different filesystem open routines */
besterror = ENOENT;
for (i = 0; file_system[i] != NULL; i++) {
error = ((*file_system[i]).fo_open)(file, f);
if (error == 0) {
f->f_ops = file_system[i];
return (fd);
}
if (error != EINVAL)
besterror = error;
}
error = besterror;
if ((f->f_flags & F_NODEV) == 0)
f->f_dev->dv_close(f);
if (error)
devclose(f);
err:
f->f_flags = 0;
errno = error;
return (-1);
}

162
lib/libstand/pager.c Normal file
View File

@ -0,0 +1,162 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
* 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.
*
* $Id$
*/
/*
* Simple paged-output and paged-viewing functions
*/
#include "stand.h"
#include <string.h>
static int p_maxlines = -1;
static int p_freelines;
static char *pager_prompt1 = " --more-- <space> page down <enter> line down <q> quit ";
static char *pager_blank = " ";
/*
* 'open' the pager
*/
void
pager_open(void)
{
int nlines;
char *cp, *lp;
nlines = 24; /* sensible default */
if ((cp = getenv("LINES")) != NULL) {
nlines = strtol(cp, &lp, 0);
}
p_maxlines = nlines - 1;
if (p_maxlines < 1)
p_maxlines = 1;
p_freelines = p_maxlines;
}
/*
* 'close' the pager
*/
void
pager_close(void)
{
p_maxlines = -1;
}
/*
* Emit lines to the pager; may not return until the user
* has responded to the prompt.
*
* Will return nonzero if the user enters 'q' or 'Q' at the prompt.
*
* XXX note that this watches outgoing newlines (and eats them), but
* does not handle wrap detection (req. count of columns).
*/
int
pager_output(const char *cp)
{
int action;
if (cp == NULL)
return(0);
for (;;) {
if (*cp == 0)
return(0);
putchar(*cp); /* always emit character */
if (*(cp++) == '\n') { /* got a newline? */
p_freelines--;
if (p_freelines <= 0) {
printf(pager_prompt1);
action = 0;
while (action == 0) {
switch(getchar()) {
case '\r':
case '\n':
p_freelines = 1;
action = 1;
break;
case ' ':
p_freelines = p_maxlines;
action = 1;
break;
case 'q':
case 'Q':
action = 2;
break;
default:
break;
}
}
printf("\r%s\r", pager_blank);
if (action == 2)
return(1);
}
}
}
}
/*
* Display from (fd).
*/
int
pager_file(char *fname)
{
char buf[80];
size_t hmuch;
int fd;
int result;
if ((fd = open(fname, O_RDONLY)) == -1) {
printf("can't open '%s': %s\n", fname, strerror(errno));
return(-1);
}
pager_open();
for (;;) {
hmuch = read(fd, buf, sizeof(buf) - 1);
if (hmuch == -1) {
result = -1;
break;
}
if (hmuch == 0) {
result = 0;
break;
}
buf[hmuch] = 0;
if (pager_output(buf)) {
result = 1;
break;
}
}
pager_close();
close(fd);
return(result);
}

355
lib/libstand/printf.c Normal file
View File

@ -0,0 +1,355 @@
/*-
* Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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 the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
* $Id: subr_prf.c,v 1.46 1998/05/28 09:30:20 phk Exp $
*/
/*
* Standaloneified version of the FreeBSD kernel printf family.
*/
#include <sys/types.h>
#include "stand.h"
/*
* Note that stdarg.h and the ANSI style va_start macro is used for both
* ANSI and traditional C compilers.
*/
#include <machine/stdarg.h>
static char *ksprintn (u_long num, int base, int *len);
static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap);
int
printf(const char *fmt, ...)
{
va_list ap;
int retval;
va_start(ap, fmt);
retval = kvprintf(fmt, putchar, NULL, 10, ap);
va_end(ap);
return retval;
}
void
vprintf(const char *fmt, va_list ap)
{
kvprintf(fmt, putchar, NULL, 10, ap);
}
/*
* Scaled down version of sprintf(3).
*/
int
sprintf(char *buf, const char *cfmt, ...)
{
int retval;
va_list ap;
va_start(ap, cfmt);
retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap);
buf[retval] = '\0';
va_end(ap);
return retval;
}
/*
* Put a number (base <= 16) in a buffer in reverse order; return an
* optional length and a pointer to the NULL terminated (preceded?)
* buffer.
*/
static char *
ksprintn(ul, base, lenp)
register u_long ul;
register int base, *lenp;
{ /* A long in base 8, plus NULL. */
static char buf[sizeof(long) * NBBY / 3 + 2];
register char *p;
p = buf;
do {
*++p = hex2ascii(ul % base);
} while (ul /= base);
if (lenp)
*lenp = p - buf;
return (p);
}
/*
* Scaled down version of printf(3).
*
* Two additional formats:
*
* The format %b is supported to decode error registers.
* Its usage is:
*
* printf("reg=%b\n", regval, "<base><arg>*");
*
* where <base> is the output base expressed as a control character, e.g.
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
* the first of which gives the bit number to be inspected (origin 1), and
* the next characters (up to a control character, i.e. a character <= 32),
* give the name of the register. Thus:
*
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
*
* would produce output:
*
* reg=3<BITTWO,BITONE>
*
* XXX: %D -- Hexdump, takes pointer and separator string:
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
* ("%*D", len, ptr, " " -> XX XX XX XX ...
*/
static int
kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
{
#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
char *p, *q, *d;
u_char *up;
int ch, n;
u_long ul;
int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
int dwidth;
char padc;
int retval = 0;
if (!func)
d = (char *) arg;
else
d = NULL;
if (fmt == NULL)
fmt = "(fmt null)\n";
if (radix < 2 || radix > 36)
radix = 10;
for (;;) {
padc = ' ';
width = 0;
while ((ch = (u_char)*fmt++) != '%') {
if (ch == '\0')
return retval;
PCHAR(ch);
}
lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
sign = 0; dot = 0; dwidth = 0;
reswitch: switch (ch = (u_char)*fmt++) {
case '.':
dot = 1;
goto reswitch;
case '#':
sharpflag = 1;
goto reswitch;
case '+':
sign = 1;
goto reswitch;
case '-':
ladjust = 1;
goto reswitch;
case '%':
PCHAR(ch);
break;
case '*':
if (!dot) {
width = va_arg(ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
} else {
dwidth = va_arg(ap, int);
}
goto reswitch;
case '0':
if (!dot) {
padc = '0';
goto reswitch;
}
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) {
n = n * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
if (dot)
dwidth = n;
else
width = n;
goto reswitch;
case 'b':
ul = va_arg(ap, int);
p = va_arg(ap, char *);
for (q = ksprintn(ul, *p++, NULL); *q;)
PCHAR(*q--);
if (!ul)
break;
for (tmp = 0; *p;) {
n = *p++;
if (ul & (1 << (n - 1))) {
PCHAR(tmp ? ',' : '<');
for (; (n = *p) > ' '; ++p)
PCHAR(n);
tmp = 1;
} else
for (; *p > ' '; ++p)
continue;
}
if (tmp)
PCHAR('>');
break;
case 'c':
PCHAR(va_arg(ap, int));
break;
case 'D':
up = va_arg(ap, u_char *);
p = va_arg(ap, char *);
if (!width)
width = 16;
while(width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q=p;*q;q++)
PCHAR(*q);
}
break;
case 'd':
ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
sign = 1;
base = 10;
goto number;
case 'l':
lflag = 1;
goto reswitch;
case 'n':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = radix;
goto number;
case 'o':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 8;
goto number;
case 'p':
ul = (u_long)va_arg(ap, void *);
base = 16;
sharpflag = 1;
goto number;
case 's':
p = va_arg(ap, char *);
if (p == NULL)
p = "(null)";
if (!dot)
n = strlen (p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;
width -= n;
if (!ladjust && width > 0)
while (width--)
PCHAR(padc);
while (n--)
PCHAR(*p++);
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 'u':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 10;
goto number;
case 'x':
ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
base = 16;
number: if (sign && (long)ul < 0L) {
neg = 1;
ul = -(long)ul;
}
p = ksprintn(ul, base, &tmp);
if (sharpflag && ul != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
if (!ladjust && width && (width -= tmp) > 0)
while (width--)
PCHAR(padc);
if (neg)
PCHAR('-');
if (sharpflag && ul != 0) {
if (base == 8) {
PCHAR('0');
} else if (base == 16) {
PCHAR('0');
PCHAR('x');
}
}
while (*p)
PCHAR(*p--);
if (ladjust && width && (width -= tmp) > 0)
while (width--)
PCHAR(padc);
break;
default:
PCHAR('%');
if (lflag)
PCHAR('l');
PCHAR(ch);
break;
}
}
#undef PCHAR
}

72
lib/libstand/random.c Normal file
View File

@ -0,0 +1,72 @@
/*-
* Copyright (c) 1992, 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)random.c 8.1 (Berkeley) 6/10/93
* $Id: random.c,v 1.6 1997/02/22 09:39:59 peter Exp $
*/
#include <sys/libkern.h>
static u_long randseed = 1;
void
srandom(seed)
u_long seed;
{
randseed = seed;
}
/*
* Pseudo-random number generator for randomizing the profiling clock,
* and whatever else we might use it for. The result is uniform on
* [0, 2^31 - 1].
*/
u_long
random()
{
register long x, hi, lo, t;
/*
* Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1).
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
*/
x = randseed;
hi = x / 127773;
lo = x % 127773;
t = 16807 * lo - 2836 * hi;
if (t <= 0)
t += 0x7fffffff;
randseed = t;
return (t);
}

225
lib/libstand/rarp.c Normal file
View File

@ -0,0 +1,225 @@
/* $NetBSD: rarp.c,v 1.16 1997/07/07 15:52:52 drochner Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: arp.c,v 1.5 93/07/15 05:52:26 leres Exp (LBL)
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <string.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
static ssize_t rarpsend(struct iodesc *, void *, size_t);
static ssize_t rarprecv(struct iodesc *, void *, size_t, time_t);
/*
* Ethernet (Reverse) Address Resolution Protocol (see RFC 903, and 826).
*/
int
rarp_getipaddress(sock)
int sock;
{
struct iodesc *d;
register struct ether_arp *ap;
struct {
u_char header[ETHER_SIZE];
struct {
struct ether_arp arp;
u_char pad[18]; /* 60 - sizeof(arp) */
} data;
} wbuf;
struct {
u_char header[ETHER_SIZE];
struct {
struct ether_arp arp;
u_char pad[24]; /* extra space */
} data;
} rbuf;
#ifdef RARP_DEBUG
if (debug)
printf("rarp: socket=%d\n", sock);
#endif
if (!(d = socktodesc(sock))) {
printf("rarp: bad socket. %d\n", sock);
return (-1);
}
#ifdef RARP_DEBUG
if (debug)
printf("rarp: d=%x\n", (u_int)d);
#endif
bzero((char*)&wbuf.data, sizeof(wbuf.data));
ap = &wbuf.data.arp;
ap->arp_hrd = htons(ARPHRD_ETHER);
ap->arp_pro = htons(ETHERTYPE_IP);
ap->arp_hln = sizeof(ap->arp_sha); /* hardware address length */
ap->arp_pln = sizeof(ap->arp_spa); /* protocol address length */
ap->arp_op = htons(ARPOP_REVREQUEST);
bcopy(d->myea, ap->arp_sha, 6);
bcopy(d->myea, ap->arp_tha, 6);
if (sendrecv(d,
rarpsend, &wbuf.data, sizeof(wbuf.data),
rarprecv, &rbuf.data, sizeof(rbuf.data)) < 0)
{
printf("No response for RARP request\n");
return (-1);
}
ap = &rbuf.data.arp;
bcopy(ap->arp_tpa, (char *)&myip, sizeof(myip));
#if 0
/* XXX - Can NOT assume this is our root server! */
bcopy(ap->arp_spa, (char *)&rootip, sizeof(rootip));
#endif
/* Compute our "natural" netmask. */
if (IN_CLASSA(myip.s_addr))
netmask = IN_CLASSA_NET;
else if (IN_CLASSB(myip.s_addr))
netmask = IN_CLASSB_NET;
else
netmask = IN_CLASSC_NET;
d->myip = myip;
return (0);
}
/*
* Broadcast a RARP request (i.e. who knows who I am)
*/
static ssize_t
rarpsend(d, pkt, len)
register struct iodesc *d;
register void *pkt;
register size_t len;
{
#ifdef RARP_DEBUG
if (debug)
printf("rarpsend: called\n");
#endif
return (sendether(d, pkt, len, bcea, ETHERTYPE_REVARP));
}
/*
* Returns 0 if this is the packet we're waiting for
* else -1 (and errno == 0)
*/
static ssize_t
rarprecv(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
{
register ssize_t n;
register struct ether_arp *ap;
u_int16_t etype; /* host order */
#ifdef RARP_DEBUG
if (debug)
printf("rarprecv: ");
#endif
n = readether(d, pkt, len, tleft, &etype);
errno = 0; /* XXX */
if (n == -1 || n < sizeof(struct ether_arp)) {
#ifdef RARP_DEBUG
if (debug)
printf("bad len=%d\n", n);
#endif
return (-1);
}
if (etype != ETHERTYPE_REVARP) {
#ifdef RARP_DEBUG
if (debug)
printf("bad type=0x%x\n", etype);
#endif
return (-1);
}
ap = (struct ether_arp *)pkt;
if (ap->arp_hrd != htons(ARPHRD_ETHER) ||
ap->arp_pro != htons(ETHERTYPE_IP) ||
ap->arp_hln != sizeof(ap->arp_sha) ||
ap->arp_pln != sizeof(ap->arp_spa) )
{
#ifdef RARP_DEBUG
if (debug)
printf("bad hrd/pro/hln/pln\n");
#endif
return (-1);
}
if (ap->arp_op != htons(ARPOP_REVREPLY)) {
#ifdef RARP_DEBUG
if (debug)
printf("bad op=0x%x\n", ntohs(ap->arp_op));
#endif
return (-1);
}
/* Is the reply for our Ethernet address? */
if (bcmp(ap->arp_tha, d->myea, 6)) {
#ifdef RARP_DEBUG
if (debug)
printf("unwanted address\n");
#endif
return (-1);
}
/* We have our answer. */
#ifdef RARP_DEBUG
if (debug)
printf("got it\n");
#endif
return (n);
}

96
lib/libstand/read.c Normal file
View File

@ -0,0 +1,96 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 <sys/param.h>
#include "stand.h"
ssize_t
read(fd, dest, bcount)
int fd;
void *dest;
size_t bcount;
{
register struct open_file *f = &files[fd];
size_t resid;
if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_READ)) {
errno = EBADF;
return (-1);
}
if (f->f_flags & F_RAW) {
twiddle();
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;
return (resid);
}
resid = bcount;
if ((errno = (f->f_ops->fo_read)(f, dest, bcount, &resid)))
return (-1);
return (ssize_t)(bcount - resid);
}

440
lib/libstand/rpc.c Normal file
View File

@ -0,0 +1,440 @@
/* $NetBSD: rpc.c,v 1.18 1998/01/23 19:27:45 thorpej Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*
* @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL)
*/
/*
* RPC functions used by NFS and bootparams.
* Note that bootparams requires the ability to find out the
* address of the server from which its response has come.
* This is supported by keeping the IP/UDP headers in the
* buffer space provided by the caller. (See rpc_fromaddr)
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <string.h>
#include "rpcv2.h"
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "rpc.h"
struct auth_info {
int32_t authtype; /* auth type */
u_int32_t authlen; /* auth length */
};
struct auth_unix {
int32_t ua_time;
int32_t ua_hostname; /* null */
int32_t ua_uid;
int32_t ua_gid;
int32_t ua_gidlist; /* null */
};
struct rpc_call {
u_int32_t rp_xid; /* request transaction id */
int32_t rp_direction; /* call direction (0) */
u_int32_t rp_rpcvers; /* rpc version (2) */
u_int32_t rp_prog; /* program */
u_int32_t rp_vers; /* version */
u_int32_t rp_proc; /* procedure */
};
struct rpc_reply {
u_int32_t rp_xid; /* request transaction id */
int32_t rp_direction; /* call direction (1) */
int32_t rp_astatus; /* accept status (0: accepted) */
union {
u_int32_t rpu_errno;
struct {
struct auth_info rok_auth;
u_int32_t rok_status;
} rpu_rok;
} rp_u;
};
/* Local forwards */
static ssize_t recvrpc(struct iodesc *, void *, size_t, time_t);
static int rpc_getport(struct iodesc *, n_long, n_long);
int rpc_xid;
int rpc_port = 0x400; /* predecrement */
/*
* Make a rpc call; return length of answer
* Note: Caller must leave room for headers.
*/
ssize_t
rpc_call(d, prog, vers, proc, sdata, slen, rdata, rlen)
register struct iodesc *d;
register n_long prog, vers, proc;
register void *sdata;
register size_t slen;
register void *rdata;
register size_t rlen;
{
register ssize_t cc;
struct auth_info *auth;
struct rpc_call *call;
struct rpc_reply *reply;
char *send_head, *send_tail;
char *recv_head, *recv_tail;
n_long x;
int port; /* host order */
#ifdef RPC_DEBUG
if (debug)
printf("rpc_call: prog=0x%x vers=%d proc=%d\n",
prog, vers, proc);
#endif
port = rpc_getport(d, prog, vers);
if (port == -1)
return (-1);
d->destport = htons(port);
/*
* Prepend authorization stuff and headers.
* Note, must prepend things in reverse order.
*/
send_head = sdata;
send_tail = (char *)sdata + slen;
/* Auth verifier is always auth_null */
send_head -= sizeof(*auth);
auth = (struct auth_info *)send_head;
auth->authtype = htonl(RPCAUTH_NULL);
auth->authlen = 0;
#if 1
/* Auth credentials: always auth unix (as root) */
send_head -= sizeof(struct auth_unix);
bzero(send_head, sizeof(struct auth_unix));
send_head -= sizeof(*auth);
auth = (struct auth_info *)send_head;
auth->authtype = htonl(RPCAUTH_UNIX);
auth->authlen = htonl(sizeof(struct auth_unix));
#else
/* Auth credentials: always auth_null (XXX OK?) */
send_head -= sizeof(*auth);
auth = send_head;
auth->authtype = htonl(RPCAUTH_NULL);
auth->authlen = 0;
#endif
/* RPC call structure. */
send_head -= sizeof(*call);
call = (struct rpc_call *)send_head;
rpc_xid++;
call->rp_xid = htonl(rpc_xid);
call->rp_direction = htonl(RPC_CALL);
call->rp_rpcvers = htonl(RPC_VER2);
call->rp_prog = htonl(prog);
call->rp_vers = htonl(vers);
call->rp_proc = htonl(proc);
/* Make room for the rpc_reply header. */
recv_head = rdata;
recv_tail = (char *)rdata + rlen;
recv_head -= sizeof(*reply);
cc = sendrecv(d,
sendudp, send_head, send_tail - send_head,
recvrpc, recv_head, recv_tail - recv_head);
#ifdef RPC_DEBUG
if (debug)
printf("callrpc: cc=%ld rlen=%lu\n", (long)cc, (u_long)rlen);
#endif
if (cc == -1)
return (-1);
if (cc <= sizeof(*reply)) {
errno = EBADRPC;
return (-1);
}
recv_tail = recv_head + cc;
/*
* Check the RPC reply status.
* The xid, dir, astatus were already checked.
*/
reply = (struct rpc_reply *)recv_head;
auth = &reply->rp_u.rpu_rok.rok_auth;
x = ntohl(auth->authlen);
if (x != 0) {
#ifdef RPC_DEBUG
if (debug)
printf("callrpc: reply auth != NULL\n");
#endif
errno = EBADRPC;
return(-1);
}
x = ntohl(reply->rp_u.rpu_rok.rok_status);
if (x != 0) {
printf("callrpc: error = %ld\n", (long)x);
errno = EBADRPC;
return(-1);
}
recv_head += sizeof(*reply);
return (ssize_t)(recv_tail - recv_head);
}
/*
* Returns true if packet is the one we're waiting for.
* This just checks the XID, direction, acceptance.
* Remaining checks are done by callrpc
*/
static ssize_t
recvrpc(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register size_t len;
time_t tleft;
{
register struct rpc_reply *reply;
ssize_t n;
int x;
errno = 0;
#ifdef RPC_DEBUG
if (debug)
printf("recvrpc: called len=%lu\n", (u_long)len);
#endif
n = readudp(d, pkt, len, tleft);
if (n <= (4 * 4))
return -1;
reply = (struct rpc_reply *)pkt;
x = ntohl(reply->rp_xid);
if (x != rpc_xid) {
#ifdef RPC_DEBUG
if (debug)
printf("recvrpc: rp_xid %d != xid %d\n", x, rpc_xid);
#endif
return -1;
}
x = ntohl(reply->rp_direction);
if (x != RPC_REPLY) {
#ifdef RPC_DEBUG
if (debug)
printf("recvrpc: rp_direction %d != REPLY\n", x);
#endif
return -1;
}
x = ntohl(reply->rp_astatus);
if (x != RPC_MSGACCEPTED) {
errno = ntohl(reply->rp_u.rpu_errno);
printf("recvrpc: reject, astat=%d, errno=%d\n", x, errno);
return -1;
}
/* Return data count (thus indicating success) */
return (n);
}
/*
* Given a pointer to a reply just received,
* dig out the IP address/port from the headers.
*/
void
rpc_fromaddr(pkt, addr, port)
void *pkt;
struct in_addr *addr;
u_short *port;
{
struct hackhdr {
/* Tail of IP header: just IP addresses */
n_long ip_src;
n_long ip_dst;
/* UDP header: */
u_int16_t uh_sport; /* source port */
u_int16_t uh_dport; /* destination port */
int16_t uh_ulen; /* udp length */
u_int16_t uh_sum; /* udp checksum */
/* RPC reply header: */
struct rpc_reply rpc;
} *hhdr;
hhdr = ((struct hackhdr *)pkt) - 1;
addr->s_addr = hhdr->ip_src;
*port = hhdr->uh_sport;
}
/*
* RPC Portmapper cache
*/
#define PMAP_NUM 8 /* need at most 5 pmap entries */
int rpc_pmap_num;
struct pmap_list {
struct in_addr addr; /* server, net order */
u_int prog; /* host order */
u_int vers; /* host order */
int port; /* host order */
} rpc_pmap_list[PMAP_NUM];
/* return port number in host order, or -1 */
int
rpc_pmap_getcache(addr, prog, vers)
struct in_addr addr; /* server, net order */
u_int prog; /* host order */
u_int vers; /* host order */
{
struct pmap_list *pl;
for (pl = rpc_pmap_list; pl < &rpc_pmap_list[rpc_pmap_num]; pl++) {
if (pl->addr.s_addr == addr.s_addr &&
pl->prog == prog && pl->vers == vers )
{
return (pl->port);
}
}
return (-1);
}
void
rpc_pmap_putcache(addr, prog, vers, port)
struct in_addr addr; /* server, net order */
u_int prog; /* host order */
u_int vers; /* host order */
int port; /* host order */
{
struct pmap_list *pl;
/* Don't overflow cache... */
if (rpc_pmap_num >= PMAP_NUM) {
/* ... just re-use the last entry. */
rpc_pmap_num = PMAP_NUM - 1;
#ifdef RPC_DEBUG
printf("rpc_pmap_putcache: cache overflow\n");
#endif
}
pl = &rpc_pmap_list[rpc_pmap_num];
rpc_pmap_num++;
/* Cache answer */
pl->addr = addr;
pl->prog = prog;
pl->vers = vers;
pl->port = port;
}
/*
* Request a port number from the port mapper.
* Returns the port in host order.
*/
int
rpc_getport(d, prog, vers)
register struct iodesc *d;
n_long prog; /* host order */
n_long vers; /* host order */
{
struct args {
n_long prog; /* call program */
n_long vers; /* call version */
n_long proto; /* call protocol */
n_long port; /* call port (unused) */
} *args;
struct res {
n_long port;
} *res;
struct {
n_long h[RPC_HEADER_WORDS];
struct args d;
} sdata;
struct {
n_long h[RPC_HEADER_WORDS];
struct res d;
n_long pad;
} rdata;
ssize_t cc;
int port;
#ifdef RPC_DEBUG
if (debug)
printf("getport: prog=0x%x vers=%d\n", prog, vers);
#endif
/* This one is fixed forever. */
if (prog == PMAPPROG)
return (PMAPPORT);
/* Try for cached answer first */
port = rpc_pmap_getcache(d->destip, prog, vers);
if (port != -1)
return (port);
args = &sdata.d;
args->prog = htonl(prog);
args->vers = htonl(vers);
args->proto = htonl(IPPROTO_UDP);
args->port = 0;
res = &rdata.d;
cc = rpc_call(d, PMAPPROG, PMAPVERS, PMAPPROC_GETPORT,
args, sizeof(*args), res, sizeof(*res));
if (cc < sizeof(*res)) {
printf("getport: %s", strerror(errno));
errno = EBADRPC;
return (-1);
}
port = (int)ntohl(res->port);
rpc_pmap_putcache(d->destip, prog, vers, port);
return (port);
}

68
lib/libstand/rpc.h Normal file
View File

@ -0,0 +1,68 @@
/* $NetBSD: rpc.h,v 1.8 1996/09/26 23:22:03 cgd Exp $ */
/*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory and its contributors.
* 4. 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.
*/
/* XXX defines we can't easily get from system includes */
#define PMAPPORT 111
#define PMAPPROG 100000
#define PMAPVERS 2
#define PMAPPROC_NULL 0
#define PMAPPROC_SET 1
#define PMAPPROC_UNSET 2
#define PMAPPROC_GETPORT 3
#define PMAPPROC_DUMP 4
#define PMAPPROC_CALLIT 5
/* RPC functions: */
ssize_t rpc_call(struct iodesc *, n_long, n_long, n_long,
void *, size_t, void *, size_t);
void rpc_fromaddr(void *, struct in_addr *, u_short *);
int rpc_pmap_getcache(struct in_addr, u_int, u_int);
void rpc_pmap_putcache(struct in_addr, u_int, u_int, int);
extern int rpc_port; /* decrement before bind */
/*
* How much space to leave in front of RPC requests.
* In 32-bit words (alignment) we have:
* 12: Ether + IP + UDP + padding
* 6: RPC call header
* 7: Auth UNIX
* 2: Auth NULL
*/
#define RPC_HEADER_WORDS 28

89
lib/libstand/rpcv2.h Normal file
View File

@ -0,0 +1,89 @@
/* $NetBSD: rpcv2.h,v 1.1 1996/02/26 23:05:32 gwr Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
*
* 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 the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)rpcv2.h 8.1 (Berkeley) 6/10/93
*/
/*
* Definitions for Sun RPC Version 2, from
* "RPC: Remote Procedure Call Protocol Specification" RFC1057
*/
/* Version # */
#define RPC_VER2 2
/* Authentication */
#define RPCAUTH_NULL 0
#define RPCAUTH_UNIX 1
#define RPCAUTH_SHORT 2
#define RPCAUTH_MAXSIZ 400
#define RPCAUTH_UNIXGIDS 16
/* Rpc Constants */
#define RPC_CALL 0
#define RPC_REPLY 1
#define RPC_MSGACCEPTED 0
#define RPC_MSGDENIED 1
#define RPC_PROGUNAVAIL 1
#define RPC_PROGMISMATCH 2
#define RPC_PROCUNAVAIL 3
#define RPC_GARBAGE 4 /* I like this one */
#define RPC_MISMATCH 0
#define RPC_AUTHERR 1
/* Authentication failures */
#define AUTH_BADCRED 1
#define AUTH_REJECTCRED 2
#define AUTH_BADVERF 3
#define AUTH_REJECTVERF 4
#define AUTH_TOOWEAK 5 /* Give em wheaties */
/* Sizes of rpc header parts */
#define RPC_SIZ 24
#define RPC_REPLYSIZ 28
/* RPC Prog definitions */
#define RPCPROG_MNT 100005
#define RPCMNT_VER1 1
#define RPCMNT_MOUNT 1
#define RPCMNT_DUMP 2
#define RPCMNT_UMOUNT 3
#define RPCMNT_UMNTALL 4
#define RPCMNT_EXPORT 5
#define RPCMNT_NAMELEN 255
#define RPCMNT_PATHLEN 1024
#define RPCPROG_NFS 100003

52
lib/libstand/saioctl.h Normal file
View File

@ -0,0 +1,52 @@
/* $NetBSD: saioctl.h,v 1.2 1994/10/26 05:45:04 cgd 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)saioctl.h 8.1 (Berkeley) 6/11/93
*/
/* ioctl's -- for disks just now */
#define SAIOHDR (('d'<<8)|1) /* next i/o includes header */
#define SAIOCHECK (('d'<<8)|2) /* next i/o checks data */
#define SAIOHCHECK (('d'<<8)|3) /* next i/o checks header & data */
#define SAIONOBAD (('d'<<8)|4) /* inhibit bad sector forwarding */
#define SAIODOBAD (('d'<<8)|5) /* enable bad sector forwarding */
#define SAIOECCLIM (('d'<<8)|6) /* set limit to ecc correction, bits */
#define SAIOECCUNL (('d'<<8)|7) /* use standard ecc procedures */
#define SAIORETRIES (('d'<<8)|8) /* set retry count for unit */
#define SAIODEVDATA (('d'<<8)|9) /* get pointer to pack label */
#define SAIOSSI (('d'<<8)|10) /* set skip sector inhibit */
#define SAIONOSSI (('d'<<8)|11) /* inhibit skip sector handling */
#define SAIOSSDEV (('d'<<8)|12) /* is device skip sector type? */
#define SAIODEBUG (('d'<<8)|13) /* enable/disable debugging */
#define SAIOGBADINFO (('d'<<8)|14) /* get bad-sector table */

305
lib/libstand/stand.h Normal file
View File

@ -0,0 +1,305 @@
/*
* 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.
*
* $Id$
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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
*/
#include <sys/types.h>
#include <sys/cdefs.h>
#include <sys/stat.h>
#ifndef NULL
#define NULL 0
#endif
/* Avoid unwanted userlandish components */
#define KERNEL
#include <sys/errno.h>
#undef KERNEL
/* 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) /* */
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 {
char *fs_name;
int (*fo_open)(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, 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);
};
/*
* 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 zipfs_fsops;
#ifdef notyet
extern struct fs_ops dosfs_fsops;
#endif
/* 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 {
char dv_name[8];
int dv_type; /* opaque type constant, arch-dependant */
int (*dv_init)(void); /* early probe call */
int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, void *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);
};
extern int errno;
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 (F_RAW) */
};
#define SOPEN_MAX 8
extern struct open_file files[];
/* 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 isupper(c) ((c) >= 'A' && (c) <= 'Z')
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#define isspace(c) ((c) == ' ' || (c) == '\t')
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define isxdigit(c) (isdigit(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
#define isascii(c) ((c) >= 0 || (c <= 0x7f))
#define isalpha(c) (isupper(c) || (islower(c)))
#define toupper(c) ((c) - 'a' + 'A')
#define tolower(c) ((c) - 'A' + 'a')
extern void setheap(void *, void *);
extern void *malloc(size_t);
extern void free(void *);
extern char *sbrk(int junk);
/* disklabel support (undocumented, may be junk) */
struct disklabel;
extern char *getdisklabel(const char *, struct disklabel *);
extern int dkcksum(struct disklabel *);
extern int printf(const char *fmt, ...);
extern void vprintf(const char *fmt, _BSD_VA_LIST_);
extern int sprintf(char *buf, const char *cfmt, ...);
extern void twiddle(void);
extern void ngets(char *, int);
#define gets(x) ngets((x), 0)
extern int fgetstr(char *buf, int size, int fd);
extern char *strerror(int);
extern int open(const char *, int);
#define O_RDONLY 0x0
#define O_WRONLY 0x1 /* writing not (yet?) supported */
#define O_RDWR 0x2
extern int close(int);
extern void closeall(void);
extern ssize_t read(int, void *, size_t);
extern ssize_t write(int, void *, size_t);
extern off_t lseek(int, off_t, int);
extern int stat(const char *, struct stat *);
extern void srandom(u_long seed);
extern u_long random(void);
/* imports from stdlib, locally modified */
extern long strtol(const char *, char **, int);
extern char *optarg; /* getopt(3) external variables */
extern int optind, opterr, optopt;
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(char *fname);
/* 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, 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, void *value,
ev_sethook_t sethook, ev_unsethook_t unsethook);
extern char *getenv(const char *name);
extern int setenv(const char *name, char *value, int overwrite);
extern int putenv(const 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 */
/* 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])
/* 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); }
/* swaps (undocumented, useful?) */
#ifdef __i386__
extern u_int32_t bswap32(u_int32_t x);
extern u_int64_t bswap64(u_int32_t x);
#endif
/* 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(char *path, struct open_file *f);
extern int null_close(struct open_file *f);
extern ssize_t null_read(struct open_file *f, void *buf, size_t size, size_t *resid);
extern ssize_t null_write(struct open_file *f, 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);
/* stuff should be in bootstrap (undocumented) */
extern int getfile(char *prompt, int mode);
/*
* Machine dependent functions and data, must be provided or stubbed by
* the consumer
*/
extern int getchar(void);
extern int ischar(void);
extern void putchar(int);
extern int devopen(struct open_file *, const char *, char **);
extern int devclose(struct open_file *f);
extern __dead void panic(const char *, ...) __attribute__((noreturn));
extern struct fs_ops *file_system[];
extern struct devsw *devsw[];

53
lib/libstand/stat.c Normal file
View File

@ -0,0 +1,53 @@
/* $NetBSD: stat.c,v 1.4 1996/01/13 22:25:43 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 "stand.h"
int
stat(str, sb)
const char *str;
struct stat *sb;
{
int fd, rv;
fd = open(str, O_RDONLY);
if (fd < 0)
return (-1);
rv = fstat(fd, sb);
(void)close(fd);
return (rv);
}

56
lib/libstand/strdup.c Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 1988, 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "stand.h"
#include <stddef.h>
#include <string.h>
char *
strdup(str)
const char *str;
{
size_t len;
char *copy = NULL;
if (str != NULL) {
len = strlen(str) + 1;
if ((copy = malloc(len)) == NULL)
return (NULL);
memcpy(copy, str, len);
}
return (copy);
}

88
lib/libstand/strerror.c Normal file
View File

@ -0,0 +1,88 @@
/* $NetBSD: strerror.c,v 1.12 1997/01/25 00:37:50 cgd 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#include "stand.h"
static struct
{
int err;
char *msg;
} errtab[] = {
{0, "no error"},
/* standard errors */
{EPERM, "operation not permitted"},
{ENOENT, "no such file or directory"},
{EIO, "input/output error"},
{ENXIO, "device not configured"},
{ENOEXEC, "exec format error"},
{EBADF, "bad file descriptor"},
{ENOMEM, "cannot allocate memory"},
{ENODEV, "operation not supported by device"},
{ENOTDIR, "not a directory"},
{EISDIR, "is a directory"},
{EINVAL, "invalid argument"},
{EMFILE, "too many open files"},
{EFBIG, "file too large"},
{EROFS, "read-only filesystem"},
{EOPNOTSUPP, "operation not supported"},
{ETIMEDOUT, "operation timed out"},
{ESTALE, "stale NFS file handle"},
{EBADRPC, "RPC struct is bad"},
{EFTYPE, "inappropriate file type or format"},
{EADAPT, "bad adaptor number"},
{ECTLR, "bad controller number"},
{EUNIT, "bad unit number"},
{ESLICE, "bad slice number"},
{EPART, "bad partition"},
{ERDLAB, "can't read disk label"},
{EUNLAB, "disk unlabelled"},
{EOFFSET, "illegal seek"},
{0, NULL}
};
char *
strerror(int err)
{
static char msg[32];
int i;
for (i = 0; errtab[i].msg != NULL; i++)
if (errtab[i].err == err)
return(errtab[i].msg);
sprintf(msg, "unknown error (%d)", err);
return(msg);
}

133
lib/libstand/strtol.c Normal file
View File

@ -0,0 +1,133 @@
/*-
* Copyright (c) 1990, 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include "stand.h"
#include <limits.h>
/*
* Convert a string to a long integer.
*
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
long
strtol(nptr, endptr, base)
const char *nptr;
char **endptr;
register int base;
{
register const char *s;
register unsigned long acc;
register unsigned char c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
/* Be sensible about NULL strings */
if (nptr == NULL)
nptr = "";
s = nptr;
/*
* Skip white space and pick up leading +/- sign if any.
* If base is 0, allow 0x for hex and 0 for octal, else
* assume decimal; if base is already 16, allow 0x.
*/
do {
c = *s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
} else if (c == '+')
c = *s++;
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
}
if (base == 0)
base = c == '0' ? 8 : 10;
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
* base. An input number that is greater than this value, if
* followed by a legal input character, is too big. One that
* is equal to this value may be valid or not; the limit
* between valid and invalid numbers is then based on the last
* digit. For instance, if the range for longs is
* [-2147483648..2147483647] and the input base is 10,
* cutoff will be set to 214748364 and cutlim to either
* 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
* a value > 214748364, or equal but the next digit is > 7 (or 8),
* the number is too big, and we will return a range error.
*
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
cutlim = cutoff % (unsigned long)base;
cutoff /= (unsigned long)base;
for (acc = 0, any = 0;; c = *s++) {
if (!isascii(c))
break;
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *)(any ? s - 1 : nptr);
return (acc);
}

400
lib/libstand/tftp.c Normal file
View File

@ -0,0 +1,400 @@
/* $NetBSD: tftp.c,v 1.4 1997/09/17 16:57:07 drochner Exp $ */
/*
* Copyright (c) 1996
* Matthias Drochner. 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 for the NetBSD Project
* by Matthias Drochner.
* 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 THE AUTHOR ``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 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.
*
*/
/*
* Simple TFTP implementation for libsa.
* Assumes:
* - socket descriptor (int) at open_file->f_devdata
* - server host IP in global servip
* Restrictions:
* - read only
* - lseek only with SEEK_SET or SEEK_CUR
* - no big time differences between transfers (<tftp timeout)
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <netinet/in_systm.h>
#include <arpa/tftp.h>
#include <string.h>
#include "stand.h"
#include "net.h"
#include "netif.h"
#include "tftp.h"
static int tftp_open(char *path, struct open_file *f);
static int tftp_close(struct open_file *f);
static int tftp_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static int tftp_write(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t tftp_seek(struct open_file *f, off_t offset, int where);
static int tftp_stat(struct open_file *f, struct stat *sb);
struct fs_ops tftp_fsops = {
"tftp", tftp_open, tftp_close, tftp_read, tftp_write, tftp_seek, tftp_stat
};
extern struct in_addr servip;
static int tftpport = 2000;
#define RSPACE 520 /* max data packet, rounded up */
struct tftp_handle {
struct iodesc *iodesc;
int currblock; /* contents of lastdata */
int islastblock; /* flag */
int validsize;
int off;
char *path; /* saved for re-requests */
struct {
u_char header[HEADER_SIZE];
struct tftphdr t;
u_char space[RSPACE];
} lastdata;
};
static int tftperrors[8] = {
0, /* ??? */
ENOENT,
EPERM,
ENOSPC,
EINVAL, /* ??? */
EINVAL, /* ??? */
EEXIST,
EINVAL /* ??? */
};
static ssize_t
recvtftp(d, pkt, len, tleft)
register struct iodesc *d;
register void *pkt;
register ssize_t len;
time_t tleft;
{
struct tftphdr *t;
len = readudp(d, pkt, len, tleft);
if (len < 8)
return (-1);
t = (struct tftphdr *) pkt;
switch (ntohs(t->th_opcode)) {
case DATA: {
int got;
if (htons(t->th_block) != d->xid) {
/*
* Expected block?
*/
return (-1);
}
if (d->xid == 1) {
/*
* First data packet from new port.
*/
register struct udphdr *uh;
uh = (struct udphdr *) pkt - 1;
d->destport = uh->uh_sport;
} /* else check uh_sport has not changed??? */
got = len - (t->th_data - (char *) t);
return got;
}
case ERROR:
if ((unsigned) ntohs(t->th_code) >= 8) {
printf("illegal tftp error %d\n", ntohs(t->th_code));
errno = EIO;
} else {
#ifdef DEBUG
printf("tftp-error %d\n", ntohs(t->th_code));
#endif
errno = tftperrors[ntohs(t->th_code)];
}
return (-1);
default:
#ifdef DEBUG
printf("tftp type %d not handled\n", ntohs(t->th_opcode));
#endif
return (-1);
}
}
/* send request, expect first block (or error) */
static int
tftp_makereq(h)
struct tftp_handle *h;
{
struct {
u_char header[HEADER_SIZE];
struct tftphdr t;
u_char space[FNAME_SIZE + 6];
} wbuf;
char *wtail;
int l;
ssize_t res;
struct tftphdr *t;
wbuf.t.th_opcode = htons((u_short) RRQ);
wtail = wbuf.t.th_stuff;
l = strlen(h->path);
bcopy(h->path, wtail, l + 1);
wtail += l + 1;
bcopy("octet", wtail, 6);
wtail += 6;
t = &h->lastdata.t;
/* h->iodesc->myport = htons(--tftpport); */
h->iodesc->myport = htons(tftpport + (getsecs() & 0x3ff));
h->iodesc->destport = htons(IPPORT_TFTP);
h->iodesc->xid = 1; /* expected block */
res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
recvtftp, t, sizeof(*t) + RSPACE);
if (res == -1)
return (errno);
h->currblock = 1;
h->validsize = res;
h->islastblock = 0;
if (res < SEGSIZE)
h->islastblock = 1; /* very short file */
return (0);
}
/* ack block, expect next */
static int
tftp_getnextblock(h)
struct tftp_handle *h;
{
struct {
u_char header[HEADER_SIZE];
struct tftphdr t;
} wbuf;
char *wtail;
int res;
struct tftphdr *t;
wbuf.t.th_opcode = htons((u_short) ACK);
wtail = (char *) &wbuf.t.th_block;
wbuf.t.th_block = htons((u_short) h->currblock);
wtail += 2;
t = &h->lastdata.t;
h->iodesc->xid = h->currblock + 1; /* expected block */
res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
recvtftp, t, sizeof(*t) + RSPACE);
if (res == -1) /* 0 is OK! */
return (errno);
h->currblock++;
h->validsize = res;
if (res < SEGSIZE)
h->islastblock = 1; /* EOF */
return (0);
}
static int
tftp_open(path, f)
char *path;
struct open_file *f;
{
struct tftp_handle *tftpfile;
struct iodesc *io;
int res;
tftpfile = (struct tftp_handle *) malloc(sizeof(*tftpfile));
if (!tftpfile)
return (ENOMEM);
tftpfile->iodesc = io = socktodesc(*(int *) (f->f_devdata));
io->destip = servip;
tftpfile->off = 0;
tftpfile->path = path; /* XXXXXXX we hope it's static */
res = tftp_makereq(tftpfile, path);
if (res) {
free(tftpfile);
return (res);
}
f->f_fsdata = (void *) tftpfile;
return (0);
}
static int
tftp_read(f, addr, size, resid)
struct open_file *f;
void *addr;
size_t size;
size_t *resid; /* out */
{
struct tftp_handle *tftpfile;
static int tc = 0;
tftpfile = (struct tftp_handle *) f->f_fsdata;
while (size > 0) {
int needblock, count;
if (!(tc++ % 16))
twiddle();
needblock = tftpfile->off / SEGSIZE + 1;
if (tftpfile->currblock > needblock) /* seek backwards */
tftp_makereq(tftpfile); /* no error check, it worked
* for open */
while (tftpfile->currblock < needblock) {
int res;
res = tftp_getnextblock(tftpfile);
if (res) { /* no answer */
#ifdef DEBUG
printf("tftp: read error\n");
#endif
return (res);
}
if (tftpfile->islastblock)
break;
}
if (tftpfile->currblock == needblock) {
int offinblock, inbuffer;
offinblock = tftpfile->off % SEGSIZE;
inbuffer = tftpfile->validsize - offinblock;
if (inbuffer < 0) {
#ifdef DEBUG
printf("tftp: invalid offset %d\n",
tftpfile->off);
#endif
return (EINVAL);
}
count = (size < inbuffer ? size : inbuffer);
bcopy(tftpfile->lastdata.t.th_data + offinblock,
addr, count);
addr += count;
tftpfile->off += count;
size -= count;
if ((tftpfile->islastblock) && (count == inbuffer))
break; /* EOF */
} else {
#ifdef DEBUG
printf("tftp: block %d not found\n", needblock);
#endif
return (EINVAL);
}
}
if (resid)
*resid = size;
return (0);
}
static int
tftp_close(f)
struct open_file *f;
{
struct tftp_handle *tftpfile;
tftpfile = (struct tftp_handle *) f->f_fsdata;
/* let it time out ... */
if (tftpfile)
free(tftpfile);
return (0);
}
static int
tftp_write(f, start, size, resid)
struct open_file *f;
void *start;
size_t size;
size_t *resid; /* out */
{
return (EROFS);
}
static int
tftp_stat(f, sb)
struct open_file *f;
struct stat *sb;
{
struct tftp_handle *tftpfile;
tftpfile = (struct tftp_handle *) f->f_fsdata;
sb->st_mode = 0444;
sb->st_nlink = 1;
sb->st_uid = 0;
sb->st_gid = 0;
sb->st_size = -1;
return (0);
}
static off_t
tftp_seek(f, offset, where)
struct open_file *f;
off_t offset;
int where;
{
struct tftp_handle *tftpfile;
tftpfile = (struct tftp_handle *) f->f_fsdata;
switch (where) {
case SEEK_SET:
tftpfile->off = offset;
break;
case SEEK_CUR:
tftpfile->off += offset;
break;
default:
errno = EOFFSET;
return (-1);
}
return (tftpfile->off);
}

36
lib/libstand/tftp.h Normal file
View File

@ -0,0 +1,36 @@
/* $NetBSD: tftp.h,v 1.1.1.1 1997/03/14 02:40:31 perry Exp $ */
/*
* Copyright (c) 1996
* Matthias Drochner. 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 for the NetBSD Project
* by Matthias Drochner.
* 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 THE AUTHOR ``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 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.
*
*/
#define IPPORT_TFTP 69

54
lib/libstand/twiddle.c Normal file
View File

@ -0,0 +1,54 @@
/*-
* Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* 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 the University of
* California, Berkeley and its contributors.
* 4. 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.
*
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
* $Id: subr_prf.c,v 1.46 1998/05/28 09:30:20 phk Exp $
*/
#include <sys/types.h>
#include "stand.h"
/* Extra functions from NetBSD standalone printf.c */
void
twiddle()
{
static int pos;
putchar("|/-\\"[pos++ & 3]);
putchar('\b');
}

704
lib/libstand/ufs.c Normal file
View File

@ -0,0 +1,704 @@
/* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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.
*
*
* Copyright (c) 1990, 1991 Carnegie Mellon University
* All Rights Reserved.
*
* Author: David Golub
*
* 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.
*/
/*
* Stand-alone file reading package.
*/
#include <sys/param.h>
#include <sys/time.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ffs/fs.h>
#include "stand.h"
#include "string.h"
static int ufs_open(char *path, struct open_file *f);
static int ufs_close(struct open_file *f);
static int ufs_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t ufs_seek(struct open_file *f, off_t offset, int where);
static int ufs_stat(struct open_file *f, struct stat *sb);
struct fs_ops ufs_fsops = {
"ufs", ufs_open, ufs_close, ufs_read, null_write, ufs_seek, ufs_stat
};
/*
* In-core open file.
*/
struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
struct dinode f_di; /* copy of on-disk inode */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
char *f_blk[NIADDR]; /* buffer for indirect block at
level i */
size_t f_blksize[NIADDR];
/* size of buffer */
daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
char *f_buf; /* buffer for data block */
size_t f_buf_size; /* size of data block */
daddr_t f_buf_blkno; /* block number of data block */
};
static int read_inode(ino_t, struct open_file *);
static int block_map(struct open_file *, daddr_t, daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
#ifdef COMPAT_UFS
static void ffs_oldfscompat(struct fs *);
#endif
/*
* Read a new inode into a file structure.
*/
static int
read_inode(inumber, f)
ino_t inumber;
struct open_file *f;
{
register struct file *fp = (struct file *)f->f_fsdata;
register struct fs *fs = fp->f_fs;
char *buf;
size_t rsize;
int rc;
/*
* Read inode and save it.
*/
buf = malloc(fs->fs_bsize);
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
buf, &rsize);
if (rc)
goto out;
if (rsize != fs->fs_bsize) {
rc = EIO;
goto out;
}
{
register struct dinode *dp;
dp = (struct dinode *)buf;
fp->f_di = dp[ino_to_fsbo(fs, inumber)];
}
/*
* Clear out the old buffers
*/
{
register int level;
for (level = 0; level < NIADDR; level++)
fp->f_blkno[level] = -1;
fp->f_buf_blkno = -1;
}
out:
free(buf);
return (rc);
}
/*
* Given an offset in a file, find the disk block number that
* contains that block.
*/
static int
block_map(f, file_block, disk_block_p)
struct open_file *f;
daddr_t file_block;
daddr_t *disk_block_p; /* out */
{
register struct file *fp = (struct file *)f->f_fsdata;
register struct fs *fs = fp->f_fs;
int level;
int idx;
daddr_t ind_block_num;
daddr_t *ind_p;
int rc;
/*
* Index structure of an inode:
*
* di_db[0..NDADDR-1] hold block numbers for blocks
* 0..NDADDR-1
*
* di_ib[0] index block 0 is the single indirect block
* holds block numbers for blocks
* NDADDR .. NDADDR + NINDIR(fs)-1
*
* di_ib[1] index block 1 is the double indirect block
* holds block numbers for INDEX blocks for blocks
* NDADDR + NINDIR(fs) ..
* NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
*
* di_ib[2] index block 2 is the triple indirect block
* holds block numbers for double-indirect
* blocks for blocks
* NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
* NDADDR + NINDIR(fs) + NINDIR(fs)**2
* + NINDIR(fs)**3 - 1
*/
if (file_block < NDADDR) {
/* Direct block. */
*disk_block_p = fp->f_di.di_db[file_block];
return (0);
}
file_block -= NDADDR;
/*
* nindir[0] = NINDIR
* nindir[1] = NINDIR**2
* nindir[2] = NINDIR**3
* etc
*/
for (level = 0; level < NIADDR; level++) {
if (file_block < fp->f_nindir[level])
break;
file_block -= fp->f_nindir[level];
}
if (level == NIADDR) {
/* Block number too high */
return (EFBIG);
}
ind_block_num = fp->f_di.di_ib[level];
for (; level >= 0; level--) {
if (ind_block_num == 0) {
*disk_block_p = 0; /* missing */
return (0);
}
if (fp->f_blkno[level] != ind_block_num) {
if (fp->f_blk[level] == (char *)0)
fp->f_blk[level] =
malloc(fs->fs_bsize);
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fp->f_fs, ind_block_num),
fs->fs_bsize,
fp->f_blk[level],
&fp->f_blksize[level]);
if (rc)
return (rc);
if (fp->f_blksize[level] != fs->fs_bsize)
return (EIO);
fp->f_blkno[level] = ind_block_num;
}
ind_p = (daddr_t *)fp->f_blk[level];
if (level > 0) {
idx = file_block / fp->f_nindir[level - 1];
file_block %= fp->f_nindir[level - 1];
} else
idx = file_block;
ind_block_num = ind_p[idx];
}
*disk_block_p = ind_block_num;
return (0);
}
/*
* Read a portion of a file into an internal buffer. Return
* the location in the buffer and the amount in the buffer.
*/
static int
buf_read_file(f, buf_p, size_p)
struct open_file *f;
char **buf_p; /* out */
size_t *size_p; /* out */
{
register struct file *fp = (struct file *)f->f_fsdata;
register struct fs *fs = fp->f_fs;
long off;
register daddr_t file_block;
daddr_t disk_block;
size_t block_size;
int rc;
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
block_size = dblksize(fs, &fp->f_di, file_block);
if (file_block != fp->f_buf_blkno) {
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
if (fp->f_buf == (char *)0)
fp->f_buf = malloc(fs->fs_bsize);
if (disk_block == 0) {
bzero(fp->f_buf, block_size);
fp->f_buf_size = block_size;
} else {
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
fsbtodb(fs, disk_block),
block_size, fp->f_buf, &fp->f_buf_size);
if (rc)
return (rc);
}
fp->f_buf_blkno = file_block;
}
/*
* Return address of byte in buffer corresponding to
* offset, and size of remainder of buffer after that
* byte.
*/
*buf_p = fp->f_buf + off;
*size_p = block_size - off;
/*
* But truncate buffer at end of file.
*/
if (*size_p > fp->f_di.di_size - fp->f_seekp)
*size_p = fp->f_di.di_size - fp->f_seekp;
return (0);
}
/*
* Search a directory for a name and return its
* i_number.
*/
static int
search_directory(name, f, inumber_p)
char *name;
struct open_file *f;
ino_t *inumber_p; /* out */
{
register struct file *fp = (struct file *)f->f_fsdata;
register struct direct *dp;
struct direct *edp;
char *buf;
size_t buf_size;
int namlen, length;
int rc;
length = strlen(name);
fp->f_seekp = 0;
while (fp->f_seekp < fp->f_di.di_size) {
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
return (rc);
dp = (struct direct *)buf;
edp = (struct direct *)(buf + buf_size);
while (dp < edp) {
if (dp->d_ino == (ino_t)0)
goto next;
#if BYTE_ORDER == LITTLE_ENDIAN
if (fp->f_fs->fs_maxsymlinklen <= 0)
namlen = dp->d_type;
else
#endif
namlen = dp->d_namlen;
if (namlen == length &&
!strcmp(name, dp->d_name)) {
/* found entry */
*inumber_p = dp->d_ino;
return (0);
}
next:
dp = (struct direct *)((char *)dp + dp->d_reclen);
}
fp->f_seekp += buf_size;
}
return (ENOENT);
}
/*
* Open a file.
*/
static int
ufs_open(path, f)
char *path;
struct open_file *f;
{
register char *cp, *ncp;
register int c;
ino_t inumber, parent_inumber;
struct file *fp;
struct fs *fs;
int rc;
size_t buf_size;
int nlinks = 0;
char namebuf[MAXPATHLEN+1];
char *buf = NULL;
/* allocate file system specific data structure */
fp = malloc(sizeof(struct file));
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
/* allocate space and read super block */
fs = malloc(SBSIZE);
fp->f_fs = fs;
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
SBLOCK, SBSIZE, (char *)fs, &buf_size);
if (rc)
goto out;
if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
rc = EINVAL;
goto out;
}
#ifdef COMPAT_UFS
ffs_oldfscompat(fs);
#endif
/*
* Calculate indirect block levels.
*/
{
register int mult;
register int level;
mult = 1;
for (level = 0; level < NIADDR; level++) {
mult *= NINDIR(fs);
fp->f_nindir[level] = mult;
}
}
inumber = ROOTINO;
if ((rc = read_inode(inumber, f)) != 0)
goto out;
cp = path;
while (*cp) {
/*
* Remove extra separators
*/
while (*cp == '/')
cp++;
if (*cp == '\0')
break;
/*
* Check that current node is a directory.
*/
if ((fp->f_di.di_mode & IFMT) != IFDIR) {
rc = ENOTDIR;
goto out;
}
/*
* Get next component of path name.
*/
{
register int len = 0;
ncp = cp;
while ((c = *cp) != '\0' && c != '/') {
if (++len > MAXNAMLEN) {
rc = ENOENT;
goto out;
}
cp++;
}
*cp = '\0';
}
/*
* Look up component in current directory.
* Save directory inumber in case we find a
* symbolic link.
*/
parent_inumber = inumber;
rc = search_directory(ncp, f, &inumber);
*cp = c;
if (rc)
goto out;
/*
* Open next component.
*/
if ((rc = read_inode(inumber, f)) != 0)
goto out;
/*
* Check for symbolic link.
*/
if ((fp->f_di.di_mode & IFMT) == IFLNK) {
int link_len = fp->f_di.di_size;
int len;
len = strlen(cp);
if (link_len + len > MAXPATHLEN ||
++nlinks > MAXSYMLINKS) {
rc = ENOENT;
goto out;
}
bcopy(cp, &namebuf[link_len], len + 1);
if (link_len < fs->fs_maxsymlinklen) {
bcopy(fp->f_di.di_shortlink, namebuf,
(unsigned) link_len);
} else {
/*
* Read file for symbolic link
*/
size_t buf_size;
daddr_t disk_block;
register struct fs *fs = fp->f_fs;
if (!buf)
buf = malloc(fs->fs_bsize);
rc = block_map(f, (daddr_t)0, &disk_block);
if (rc)
goto out;
twiddle();
rc = (f->f_dev->dv_strategy)(f->f_devdata,
F_READ, fsbtodb(fs, disk_block),
fs->fs_bsize, buf, &buf_size);
if (rc)
goto out;
bcopy((char *)buf, namebuf, (unsigned)link_len);
}
/*
* If relative pathname, restart at parent directory.
* If absolute pathname, restart at root.
*/
cp = namebuf;
if (*cp != '/')
inumber = parent_inumber;
else
inumber = (ino_t)ROOTINO;
if ((rc = read_inode(inumber, f)) != 0)
goto out;
}
}
/*
* Found terminal component.
*/
rc = 0;
out:
if (buf)
free(buf);
if (rc) {
if (fp->f_buf)
free(fp->f_buf);
free(fp->f_fs);
free(fp);
}
return (rc);
}
static int
ufs_close(f)
struct open_file *f;
{
register struct file *fp = (struct file *)f->f_fsdata;
int level;
f->f_fsdata = (void *)0;
if (fp == (struct file *)0)
return (0);
for (level = 0; level < NIADDR; level++) {
if (fp->f_blk[level])
free(fp->f_blk[level]);
}
if (fp->f_buf)
free(fp->f_buf);
free(fp->f_fs);
free(fp);
return (0);
}
/*
* Copy a portion of a file into kernel memory.
* Cross block boundaries when necessary.
*/
static int
ufs_read(f, start, size, resid)
struct open_file *f;
void *start;
size_t size;
size_t *resid; /* out */
{
register struct file *fp = (struct file *)f->f_fsdata;
register size_t csize;
char *buf;
size_t buf_size;
int rc = 0;
register char *addr = start;
while (size != 0) {
if (fp->f_seekp >= fp->f_di.di_size)
break;
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
break;
csize = size;
if (csize > buf_size)
csize = buf_size;
bcopy(buf, addr, csize);
fp->f_seekp += csize;
addr += csize;
size -= csize;
}
if (resid)
*resid = size;
return (rc);
}
static off_t
ufs_seek(f, offset, where)
struct open_file *f;
off_t offset;
int where;
{
register struct file *fp = (struct file *)f->f_fsdata;
switch (where) {
case SEEK_SET:
fp->f_seekp = offset;
break;
case SEEK_CUR:
fp->f_seekp += offset;
break;
case SEEK_END:
fp->f_seekp = fp->f_di.di_size - offset;
break;
default:
return (-1);
}
return (fp->f_seekp);
}
static int
ufs_stat(f, sb)
struct open_file *f;
struct stat *sb;
{
register struct file *fp = (struct file *)f->f_fsdata;
/* only important stuff */
sb->st_mode = fp->f_di.di_mode;
sb->st_uid = fp->f_di.di_uid;
sb->st_gid = fp->f_di.di_gid;
sb->st_size = fp->f_di.di_size;
return (0);
}
#ifdef COMPAT_UFS
/*
* Sanity checks for old file systems.
*
* XXX - goes away some day.
*/
static void
ffs_oldfscompat(fs)
struct fs *fs;
{
int i;
fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
fs->fs_nrpos = 8; /* XXX */
if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
quad_t sizepb = fs->fs_bsize; /* XXX */
/* XXX */
fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
for (i = 0; i < NIADDR; i++) { /* XXX */
sizepb *= NINDIR(fs); /* XXX */
fs->fs_maxfilesize += sizepb; /* XXX */
} /* XXX */
fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
} /* XXX */
}
#endif

96
lib/libstand/write.c Normal file
View File

@ -0,0 +1,96 @@
/* $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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 <sys/param.h>
#include "stand.h"
ssize_t
write(fd, dest, bcount)
int fd;
void *dest;
size_t bcount;
{
register struct open_file *f = &files[fd];
size_t resid;
if ((unsigned)fd >= SOPEN_MAX || !(f->f_flags & F_WRITE)) {
errno = EBADF;
return (-1);
}
if (f->f_flags & F_RAW) {
twiddle();
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
btodb(f->f_offset), bcount, 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 (0);
}

316
lib/libstand/zipfs.c Normal file
View File

@ -0,0 +1,316 @@
/*
* 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.
*
* $Id$
*
*/
#include "stand.h"
#include <sys/stat.h>
#include <string.h>
#include <zlib.h>
#define Z_BUFSIZE 2048 /* XXX larger? */
struct z_file
{
int zf_rawfd;
z_stream zf_zstream;
char zf_buf[Z_BUFSIZE];
};
static int zf_fill(struct z_file *z);
static int zf_open(char *path, struct open_file *f);
static int zf_close(struct open_file *f);
static int zf_read(struct open_file *f, void *buf, size_t size, size_t *resid);
static off_t zf_seek(struct open_file *f, off_t offset, int where);
static int zf_stat(struct open_file *f, struct stat *sb);
struct fs_ops zipfs_fsops = {
"zip",
zf_open,
zf_close,
zf_read,
null_write,
zf_seek,
zf_stat
};
void *
calloc(int items, size_t size)
{
return(malloc(items * size));
}
static int
zf_fill(struct z_file *zf)
{
int result;
int req;
req = Z_BUFSIZE - zf->zf_zstream.avail_in;
result = 0;
/* If we need more */
if (req > 0) {
/* move old data to bottom of buffer */
if (req < Z_BUFSIZE)
bcopy(zf->zf_buf + req, zf->zf_buf, Z_BUFSIZE - req);
/* read to fill buffer and update availibility data */
result = read(zf->zf_rawfd, zf->zf_buf + zf->zf_zstream.avail_in, req);
zf->zf_zstream.next_in = zf->zf_buf;
if (result >= 0)
zf->zf_zstream.avail_in += result;
}
return(result);
}
/*
* Adapted from get_byte/check_header in libz
*
* Returns 0 if the header is OK, nonzero if not.
*/
static int
get_byte(struct z_file *zf)
{
if ((zf->zf_zstream.avail_in == 0) && (zf_fill(zf) == -1))
return(-1);
zf->zf_zstream.avail_in--;
return(*(zf->zf_zstream.next_in)++);
}
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
static int
check_header(struct z_file *zf)
{
int method; /* method byte */
int flags; /* flags byte */
uInt len;
int c;
/* Check the gzip magic header */
for (len = 0; len < 2; len++) {
c = get_byte(zf);
if (c != gz_magic[len]) {
return(1);
}
}
method = get_byte(zf);
flags = get_byte(zf);
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
return(1);
}
/* Discard time, xflags and OS code: */
for (len = 0; len < 6; len++) (void)get_byte(zf);
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
len = (uInt)get_byte(zf);
len += ((uInt)get_byte(zf))<<8;
/* len is garbage if EOF but the loop below will quit anyway */
while (len-- != 0 && get_byte(zf) != -1) ;
}
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
while ((c = get_byte(zf)) != 0 && c != -1) ;
}
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
while ((c = get_byte(zf)) != 0 && c != -1) ;
}
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) c = get_byte(zf);
}
/* if there's data left, we're in business */
return((c == -1) ? 1 : 0);
}
static int
zf_open(char *fname, struct open_file *f)
{
static char *zfname;
int rawfd;
struct z_file *zf;
char *cp;
int error;
struct stat sb;
/* Have to be in "just read it" mode */
if (f->f_flags != F_READ)
return(EPERM);
/* If the name already ends in .gz, ignore it */
if ((cp = strrchr(fname, '.')) && !strcmp(cp, ".gz"))
return(ENOENT);
/* Construct new name */
zfname = malloc(strlen(fname) + 3);
sprintf(zfname, "%s.gz", fname);
/* Try to open the compressed datafile */
rawfd = open(zfname, O_RDONLY);
free(zfname);
if (rawfd == -1)
return(ENOENT);
if (fstat(rawfd, &sb) < 0) {
printf("zf_open: stat failed\n");
close(rawfd);
return(ENOENT);
}
if (!S_ISREG(sb.st_mode)) {
printf("zf_open: not a file\n");
close(rawfd);
return(EISDIR); /* best guess */
}
/* Allocate a z_file structure, populate it */
zf = malloc(sizeof(struct z_file));
bzero(zf, sizeof(struct z_file));
zf->zf_rawfd = rawfd;
/* Verify that the file is gzipped (XXX why do this afterwards?) */
if (check_header(zf)) {
close(zf->zf_rawfd);
inflateEnd(&(zf->zf_zstream));
free(zf);
return(EFTYPE);
}
/* Initialise the inflation engine */
if ((error = inflateInit2(&(zf->zf_zstream), -15)) != Z_OK) {
printf("zf_open: inflateInit returned %d : %s\n", error, zf->zf_zstream.msg);
close(zf->zf_rawfd);
free(zf);
return(EIO);
}
/* Looks OK, we'll take it */
f->f_fsdata = zf;
return(0);
}
static int
zf_close(struct open_file *f)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
inflateEnd(&(zf->zf_zstream));
close(zf->zf_rawfd);
free(zf);
return(0);
}
static int
zf_read(struct open_file *f, void *buf, size_t size, size_t *resid)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
int error;
zf->zf_zstream.next_out = buf; /* where and how much */
zf->zf_zstream.avail_out = size;
while (zf->zf_zstream.avail_out) {
if ((zf->zf_zstream.avail_in == 0) && (zf_fill(zf) == -1)) {
printf("zf_read: fill error\n");
return(-1);
}
if (zf->zf_zstream.avail_in == 0) { /* oops, unexpected EOF */
printf("zf_read: unexpected EOF\n");
break;
}
error = inflate(&zf->zf_zstream, Z_SYNC_FLUSH); /* decompression pass */
if (error == Z_STREAM_END) { /* EOF, all done */
break;
}
if (error != Z_OK) { /* argh, decompression error */
printf("inflate: %s\n", zf->zf_zstream.msg);
errno = EIO;
return(-1);
}
}
if (resid != NULL)
*resid = zf->zf_zstream.avail_out;
return(0);
}
static off_t
zf_seek(struct open_file *f, off_t offset, int where)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
off_t target;
char discard[16];
switch (where) {
case SEEK_SET:
target = offset;
break;
case SEEK_CUR:
target = offset + zf->zf_zstream.total_out;
break;
default:
target = -1;
}
/* Can we get there from here? */
if (target < zf->zf_zstream.total_out) {
errno = EOFFSET;
return -1;
}
/* skip forwards if required */
while (target > zf->zf_zstream.total_out) {
if (zf_read(f, discard, min(sizeof(discard), target - zf->zf_zstream.total_out), NULL) == -1)
return(-1);
}
/* This is where we are (be honest if we overshot) */
return (zf->zf_zstream.total_out);
}
static int
zf_stat(struct open_file *f, struct stat *sb)
{
struct z_file *zf = (struct z_file *)f->f_fsdata;
int result;
/* stat as normal, but indicate that size is unknown */
if ((result = fstat(zf->zf_rawfd, sb)) == 0)
sb->st_size = -1;
return(result);
}