⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftplib.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: tftplib.c,v 1.5 2002/08/15 09:00:45 pefo Exp $ *//* * Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com) *  * 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 Opsycon AB, Sweden. * 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. * */#undef _KERNEL#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/file.h>#include <sys/time.h>#include <sys/syslog.h>#include <sys/endian.h>#include <netinet/in.h>#include <arpa/tftp.h>#include <stdio.h>#include <errno.h>#include <netdb.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <file.h>#include "netio.h"#include <pmon.h>extern void log __P((int kind, const char *fmt, ...));extern in_addr_t inet_addr __P((const char *));#ifdef TFTPDBGstatic int	tftptrace;#endifstatic const char spinner[] = "-\\|/";static const int tftperrmap[] = {    EIO,	/* EUNDEF	not defined */    ENOENT,	/* ENOTFOUND	file not found */    EACCES,	/* EACCESS	access violation */    ENOSPC,	/* ENOSPACE	disk full or allocation exceeded */    EIO,	/* EBADOP	illegal TFTP operation */    EINVAL,	/* EBADID	unknown transfer ID */    EEXIST,	/* EEXISTS	file already exists */    EACCES	/* ENOUSER	no such user */};#define	TIMEOUT		2		/* secs between rexmts */#define MAXREXMT	10		/* no of rexmts */#define PKTSIZE		(SEGSIZE+4)struct tftpfile {    struct sockaddr_in sin;    u_short	block;    short	flags;    short	eof;    int		sock;    int 	start;    int		end;    int		foffs;    char	buf[PKTSIZE];};static int	tftpopen  (int, struct Url *, int, int);static int	tftpread  (int, void *, int);static int	tftpwrite (int, const void *, int);static off_t	tftplseek (int, long, int);static int	tftpioctl (int, int, void *);static int	tftpclose (int);static NetFileOps tftpops = {	"tftp",	tftpopen,	tftpread,	tftpwrite,	tftplseek,	tftpioctl,	tftpclose};static void init_netfs __P((void)) __attribute__ ((constructor));static void   init_netfs(){	/*	 * Install ram based file system.	 */	netfs_init(&tftpops);}static int	tftprrq (struct tftpfile *tfp, struct tftphdr *req, int size);static int	tftpwrq (struct tftpfile *tfp, struct tftphdr *req, int size);static void	tftpnxtblk (struct tftpfile *tfp);static int	makerequest (int request, const char *name, struct tftphdr *tp,			     const char *mode);#ifdef TFTPDBGstatic void	tpacket (char *s, struct tftphdr *tp, int n);#endifstatic int	synchnet (int f);static inttftpopen (int fd, struct Url *url, int flags, int perms){	struct hostent *hp;	struct servent *sp;	const char *mode;	char *host;	char hbuf[MAXHOSTNAMELEN];	char reqbuf[PKTSIZE];	struct tftpfile *tfp;	struct tftphdr *rp;	int oflags, size;	NetFile *nfp = (NetFile *)_file[fd].data;		oflags = flags & O_ACCMODE; 	if (oflags != O_RDONLY && oflags != O_WRONLY) {		errno = EACCES;		return -1;	}	sp = getservbyname("tftp", "udp");	if (!sp) {		errno = EPROTONOSUPPORT;		return -1;	}#ifdef TFTPDBG	tftptrace = getenv ("tftptrace") ? 1 : 0;#endif	if (strlen(url->hostname) != 0) {		host = url->hostname;	} else {		host = getenv ("tftphost");		if (!host) {			log (LOG_INFO, "tftp: missing/bad host name: %s\n", url->filename);			errno = EDESTADDRREQ;			return -1;		}	}	tfp = (struct tftpfile *) malloc (sizeof (struct tftpfile));	if (!tfp) {		errno = ENOBUFS;		return -1;	}	bzero (tfp, sizeof (struct tftpfile));	nfp->data = (void *)tfp;		tfp->sock = socket(AF_INET, SOCK_DGRAM, 0);	if (tfp->sock < 0)		goto error;	tfp->sin.sin_family = AF_INET;	if (bind(tfp->sock, (struct sockaddr *)&tfp->sin, sizeof (tfp->sin)) < 0)		goto error;		hp = gethostbyname(host);	if (hp) {		tfp->sin.sin_family = hp->h_addrtype;		bcopy(hp->h_addr, (void *)&tfp->sin.sin_addr, hp->h_length);		strncpy (hbuf, hp->h_name, sizeof(hbuf) - 1);		hbuf[sizeof(hbuf)-1] = '\0';		host = hbuf;	} else {		tfp->sin.sin_family = AF_INET;		tfp->sin.sin_addr.s_addr = inet_addr (host);		if (tfp->sin.sin_addr.s_addr == -1) {			log (LOG_INFO, "tftp: bad internet address: %s\n", host);			errno = EADDRNOTAVAIL;			goto error;		}	}		tfp->sin.sin_port = sp->s_port;		rp = (struct tftphdr *)reqbuf;	tfp->flags = flags;	mode = "octet";	if (oflags == O_RDONLY) {		tfp->block = 1;		size = makerequest(RRQ, url->filename, rp, mode);		size = tftprrq (tfp, rp, size);		tfp->end = tfp->start + size;	} else {		tfp->block = 0;		size = makerequest(WRQ, url->filename, rp, mode);		size = tftpwrq (tfp, rp, size - 4);	}		if (size >= 0)		return 0;error:	if (tfp->sock >= 0)		close (tfp->sock);	free (tfp);	return -1;}static inttftpread (fd, buf, nread)    int fd;    void *buf;    int nread;{	NetFile	*nfp;	struct tftpfile *tfp;	struct tftphdr *rp;	int nb, n;	nfp = (NetFile *)_file[fd].data;	tfp = (struct tftpfile *)nfp->data;    	if ((tfp->flags & O_ACCMODE) != O_RDONLY) {		errno = EPERM;		return (-1);	}	rp = (struct tftphdr *) tfp->buf;	/* continue while more bytes wanted, and more available */	for (nb = nread; nb != 0 && tfp->start < tfp->end; ) {		if (tfp->foffs >= tfp->start && tfp->foffs < tfp->end) {			/* got some data that's in range */			n = tfp->end - tfp->foffs;			if (n > nb) n = nb;			bcopy (&rp->th_data[tfp->foffs - tfp->start], buf, n);			tfp->foffs += n;			buf += n;			nb -= n;		} 		if (tfp->foffs >= tfp->end) {			/* buffer is empty, ack last packet and refill */			struct tftphdr ack;			ack.th_opcode = htons((u_short)ACK);			ack.th_block = htons((u_short)tfp->block);			tftpnxtblk (tfp);			n = tftprrq (tfp, &ack, 4);			if (n < 0)				return (-1);			tfp->start = tfp->end;			tfp->end   = tfp->start + n;		}	}		return nread - nb;}static inttftpwrite (fd, buf, nwrite)    int fd;    const void *buf;    int nwrite;{	NetFile *nfp;	struct tftpfile *tfp;	struct tftphdr *dp;	int nb, n;	nfp = (NetFile *)_file[fd].data;	tfp = (struct tftpfile *)nfp->data;	if ((tfp->flags & O_ACCMODE) != O_WRONLY) {		errno = EPERM;		return (-1);	}	dp = (struct tftphdr *)tfp->buf;	for (nb = nwrite; nb != 0; ) {		n = SEGSIZE - tfp->end;		if (n > nb) n = nb;		bcopy (buf, &dp->th_data[tfp->end], n);		tfp->end += n;		tfp->foffs += n;		buf += n;		nb -= n;		if (tfp->end == SEGSIZE) {			/* buffer is full, send it */			tftpnxtblk (tfp);			dp->th_opcode = htons((u_short)DATA);			dp->th_block = htons((u_short)tfp->block);			n = tftpwrq (tfp, dp, tfp->end);			if (n < 0)				return (-1);			tfp->end = 0;		}	}	return nwrite - nb;}static off_ttftplseek (fd, offs, how)    int fd;    long offs;    int how;{	NetFile *nfp;	struct tftpfile *tfp;	long noffs;	nfp = (NetFile *)_file[fd].data;	tfp = (struct tftpfile *)nfp->data;	switch (how) {		case SEEK_SET:			noffs = offs; 			break;		case SEEK_CUR:			noffs = tfp->foffs + offs; 			break;		case SEEK_END:		default:			return -1;	}		if ((tfp->flags & O_ACCMODE) == O_WRONLY) {		if (noffs != tfp->foffs) {			errno = ESPIPE;			return (-1);		}	} else {		if (noffs < tfp->start) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -