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:
parent
5879dcdb05
commit
6b4f575cb1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/MSMITH/; revision=38451
116
lib/libstand/Makefile
Normal file
116
lib/libstand/Makefile
Normal 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
40
lib/libstand/__main.c
Normal 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
244
lib/libstand/alloc.c
Normal 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
310
lib/libstand/arp.c
Normal 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
35
lib/libstand/bcd.c
Normal 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
396
lib/libstand/bootp.c
Normal 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
137
lib/libstand/bootp.h
Normal 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
449
lib/libstand/bootparam.c
Normal 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
5
lib/libstand/bootparam.h
Normal 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
37
lib/libstand/bswap.c
Normal 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
401
lib/libstand/cd9660.c
Normal 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
96
lib/libstand/close.c
Normal 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
77
lib/libstand/closeall.c
Normal 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
62
lib/libstand/dev.c
Normal 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
255
lib/libstand/dev_net.c
Normal 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
7
lib/libstand/dev_net.h
Normal 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
660
lib/libstand/dosfs.c
Normal 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
120
lib/libstand/dosfs.h
Normal 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
212
lib/libstand/environment.c
Normal 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
151
lib/libstand/ether.c
Normal 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
60
lib/libstand/fstat.c
Normal 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
112
lib/libstand/getopt.c
Normal 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
110
lib/libstand/gets.c
Normal 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
33
lib/libstand/globals.c
Normal 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
316
lib/libstand/gzipfs.c
Normal 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
263
lib/libstand/if_ether.h
Normal 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
83
lib/libstand/in_cksum.c
Normal 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
89
lib/libstand/ioctl.c
Normal 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
54
lib/libstand/iodesc.h
Normal 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
456
lib/libstand/libstand.3
Normal 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
102
lib/libstand/lseek.c
Normal 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
503
lib/libstand/net.c
Normal 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
122
lib/libstand/net.h
Normal 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
332
lib/libstand/netif.c
Normal 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
65
lib/libstand/netif.h
Normal 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
653
lib/libstand/nfs.c
Normal 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
37
lib/libstand/nfs.h
Normal 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
166
lib/libstand/nfsv2.h
Normal 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
105
lib/libstand/nullfs.c
Normal 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
137
lib/libstand/open.c
Normal 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
162
lib/libstand/pager.c
Normal 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
355
lib/libstand/printf.c
Normal 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
72
lib/libstand/random.c
Normal 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
225
lib/libstand/rarp.c
Normal 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
96
lib/libstand/read.c
Normal 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
440
lib/libstand/rpc.c
Normal 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
68
lib/libstand/rpc.h
Normal 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
89
lib/libstand/rpcv2.h
Normal 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
52
lib/libstand/saioctl.h
Normal 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
305
lib/libstand/stand.h
Normal 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
53
lib/libstand/stat.c
Normal 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
56
lib/libstand/strdup.c
Normal 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
88
lib/libstand/strerror.c
Normal 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
133
lib/libstand/strtol.c
Normal 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
400
lib/libstand/tftp.c
Normal 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
36
lib/libstand/tftp.h
Normal 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
54
lib/libstand/twiddle.c
Normal 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
704
lib/libstand/ufs.c
Normal 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
96
lib/libstand/write.c
Normal 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
316
lib/libstand/zipfs.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user