io.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:10k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/io.c 2.15 1999/11/16 19:36:21 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5c.
- Functions for file input and output.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1996,97,98,99 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef __STDC__
- #include <stdarg.h>
- #else
- #include <varargs.h>
- #endif
- #include <sys/time.h>
- #include <sys/types.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <errno.h>
- #include "wwwoffle.h"
- #include "misc.h"
- #define BUFSIZE 64
- /*+ The buffer of data from each of the files. +*/
- static char **fdbuf=NULL;
- /*+ The number of bytes of data buffered for each file. +*/
- static int *fdbytes=NULL;
- /*+ The number of file buffers allocated. +*/
- static int nfdbuf=0;
- static int read_into_buffer(int fd);
- static int read_into_buffer_with_timeout(int fd,int timeout);
- static int read_from_buffer(int fd,char *buffer,int n);
- /*++++++++++++++++++++++++++++++++++++++
- Call fgets and realloc the buffer as needed to get a whole line.
- char *fgets_realloc Returns the modified buffer (NULL at the end of the file).
- char *buffer The current buffer.
- FILE *file The file to read from.
- ++++++++++++++++++++++++++++++++++++++*/
- char *fgets_realloc(char *buffer,FILE *file)
- {
- int n=0;
- char *buf;
- if(!buffer)
- buffer=(char*)malloc((BUFSIZE+1));
- while((buf=fgets(&buffer[n],BUFSIZE,file)))
- {
- int s=strlen(buf);
- n+=s;
- if(buffer[n-1]=='n')
- break;
- else
- buffer=(char*)realloc(buffer,n+(BUFSIZE+1));
- }
- if(!buf)
- {free(buffer);buffer=NULL;}
- return(buffer);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Initialise the buffer used for this file descriptor.
- int fd The file descriptor to initialise.
- ++++++++++++++++++++++++++++++++++++++*/
- void init_buffer(int fd)
- {
- if(fd==-1)
- return;
- if(fd>=nfdbuf)
- {
- fdbuf=(char**)realloc((void*)fdbuf,(fd+1)*sizeof(char**));
- fdbytes=(int*)realloc((void*)fdbytes,(fd+1)*sizeof(int));
- for(;nfdbuf<=fd;nfdbuf++)
- {
- fdbuf[nfdbuf]=NULL;
- fdbytes[nfdbuf]=0;
- }
- }
- if(!fdbuf[fd])
- fdbuf[fd]=(char*)malloc(BUFSIZE);
- fdbytes[fd]=0;
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read all of the data from the file descriptor and dump it.
- int empty_buffer Returns the amount that was read.
- int fd The file descriptor to read from.
- ++++++++++++++++++++++++++++++++++++++*/
- int empty_buffer(int fd)
- {
- int nr=fdbytes[fd];
- while(1)
- {
- int n;
- fd_set readfd;
- struct timeval tv;
- FD_ZERO(&readfd);
- FD_SET(fd,&readfd);
- tv.tv_sec=tv.tv_usec=0;
- if(select(fd+1,&readfd,NULL,NULL,&tv)<=0)
- return(nr);
- n=read(fd,fdbuf[fd],BUFSIZE);
- if(n>0)
- nr+=n;
- else
- return(nr);
- }
- return(nr);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read data from a file descriptor.
- int read_data Returns the number of bytes read or 0 for end of file.
- int fd The file descriptor.
- char *buffer The buffer to put the data into.
- int n The number of bytes read.
- ++++++++++++++++++++++++++++++++++++++*/
- int read_data(int fd,char *buffer,int n)
- {
- int nr;
- if(fdbytes[fd])
- nr=read_from_buffer(fd,buffer,n);
- else
- nr=read(fd,buffer,n);
- return(nr);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read data from a file descriptor, with a timeout.
- int read_or_timeout Returns the number of bytes read or -1 for a timeout.
- int fd The file descriptor.
- char *buffer The buffer to put the data into.
- int n The number of bytes read.
- int timeout The time in seconds to wait for the data.
- ++++++++++++++++++++++++++++++++++++++*/
- int read_data_or_timeout(int fd,char *buffer,int n,int timeout)
- {
- int nr;
- if(fdbytes[fd])
- nr=read_from_buffer(fd,buffer,n);
- else
- {
- fd_set readfd;
- struct timeval tv;
- FD_ZERO(&readfd);
- FD_SET(fd,&readfd);
- tv.tv_sec=timeout;
- tv.tv_usec=0;
- if(select(fd+1,&readfd,NULL,NULL,&tv)<=0)
- return(-1);
- nr=read(fd,buffer,n);
- }
- return(nr);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read a single line of data from a file descriptor.
- char *read_line Returns the modified string or NULL for the end of file.
- int fd The file descriptor.
- char *line The previously allocated line of data.
- This is a replacement for the previous fgets_realloc() function with file descriptors instead of stdio.
- ++++++++++++++++++++++++++++++++++++++*/
- char *read_line(int fd,char *line)
- {
- int found=0,eof=0;
- int n=0;
- if(!line)
- line=(char*)malloc((BUFSIZE+1));
- do
- {
- int i;
- if(!fdbytes[fd])
- if(read_into_buffer(fd)<=0)
- {eof=1;break;}
- for(i=0;i<fdbytes[fd];i++)
- if(fdbuf[fd][i]=='n')
- {
- found=1;
- n+=read_from_buffer(fd,&line[n],i+1);
- line[n]=0;
- break;
- }
- if(!found)
- {
- n+=read_from_buffer(fd,&line[n],BUFSIZE);
- line=(char*)realloc((void*)line,n+(BUFSIZE+1));
- }
- }
- while(!found && !eof);
- if(eof)
- {free(line);line=NULL;}
- return(line);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read a single line of data from a file descriptor with a timeout.
- char *read_line Returns the modified string or NULL for the end of file or timeout.
- int fd The file descriptor.
- char *line The previously allocated line of data.
- int timeout The time in seconds to wait for the data.
- This is a replacement for the previous fgets_realloc() function with file descriptors instead of stdio.
- ++++++++++++++++++++++++++++++++++++++*/
- char *read_line_or_timeout(int fd,char *line,int timeout)
- {
- int found=0,eof=0;
- int n=0;
- if(!line)
- line=(char*)malloc((BUFSIZE+1));
- do
- {
- int i;
- if(!fdbytes[fd])
- if(read_into_buffer_with_timeout(fd,timeout)<=0)
- {eof=1;break;}
- for(i=0;i<fdbytes[fd];i++)
- if(fdbuf[fd][i]=='n')
- {
- found=1;
- n+=read_from_buffer(fd,&line[n],i+1);
- line[n]=0;
- break;
- }
- if(!found)
- {
- n+=read_from_buffer(fd,&line[n],BUFSIZE);
- line=(char*)realloc((void*)line,n+(BUFSIZE+1));
- }
- }
- while(!found && !eof);
- if(eof)
- {free(line);line=NULL;}
- return(line);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read some data from a file descriptor and buffer it.
- int read_and_buffer Returns the number of bytes read.
- int fd The file descriptor to read from.
- ++++++++++++++++++++++++++++++++++++++*/
- static int read_into_buffer(int fd)
- {
- int n;
- n=read(fd,fdbuf[fd]+fdbytes[fd],BUFSIZE-fdbytes[fd]);
- fdbytes[fd]+=n;
- return(n);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read some data from a file descriptor and buffer it with a timeout.
- int read_and_buffer Returns the number of bytes read.
- int fd The file descriptor to read from.
- int timeout The time in seconds to wait for the data.
- ++++++++++++++++++++++++++++++++++++++*/
- static int read_into_buffer_with_timeout(int fd,int timeout)
- {
- int n;
- fd_set readfd;
- struct timeval tv;
- FD_ZERO(&readfd);
- FD_SET(fd,&readfd);
- tv.tv_sec=timeout;
- tv.tv_usec=0;
- if(select(fd+1,&readfd,NULL,NULL,&tv)<=0)
- return(-1);
- n=read(fd,fdbuf[fd]+fdbytes[fd],BUFSIZE-fdbytes[fd]);
- fdbytes[fd]+=n;
- return(n);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read some data from the buffer.
- int read_from_buffer Returns the number of bytes read.
- int fd The file descriptor buffer to read from.
- char *buffer The buffer to copy the data into.
- int n The maximum number of bytes to read.
- ++++++++++++++++++++++++++++++++++++++*/
- static int read_from_buffer(int fd,char *buffer,int n)
- {
- if(n>=fdbytes[fd])
- {
- memcpy(buffer,fdbuf[fd],fdbytes[fd]);
- n=fdbytes[fd];
- fdbytes[fd]=0;
- }
- else
- {
- memcpy(buffer,fdbuf[fd],n);
- fdbytes[fd]-=n;
- memmove(fdbuf[fd],fdbuf[fd]+n,fdbytes[fd]);
- }
- return(n);
- }
- /*++++++++++++++++++++++++++++++++++++++
- A function to write binary data to a file descriptor instead of write().
- int write_data Returns the number of bytes written.
- int fd The file descriptor.
- const char *data The data.
- int n The number of bytes of data.
- ++++++++++++++++++++++++++++++++++++++*/
- int write_data(int fd,const char *data,int n)
- {
- n=write(fd,data,n);
- return(n);
- }
- /*++++++++++++++++++++++++++++++++++++++
- A function to write a simple string to a file descriptor like fputs does to a FILE*.
- int write_string Returns the number of bytes written.
- int fd The file descriptor.
- const char *str The string.
- ++++++++++++++++++++++++++++++++++++++*/
- int write_string(int fd,const char *str)
- {
- int n=strlen(str);
- n=write(fd,str,n);
- return(n);
- }
- /*++++++++++++++++++++++++++++++++++++++
- A function to write a formatted string to a file descriptor like fprintf does to a FILE*.
- int write_formatted Returns the number of bytes written.
- int fd The file descriptor.
- const char *fmt The format string.
- ... The other arguments.
- ++++++++++++++++++++++++++++++++++++++*/
- int write_formatted(int fd,const char *fmt,...)
- {
- int i,n,width;
- char *str,*strp;
- va_list ap;
- /* Estimate the length of the string. */
- #ifdef __STDC__
- va_start(ap,fmt);
- #else
- va_start(ap);
- #endif
- n=strlen(fmt);
- for(i=0;fmt[i];i++)
- if(fmt[i]=='%')
- {
- i++;
- if(fmt[i]=='%')
- continue;
- width=atoi(fmt+i);
- if(width<0)
- width=-width;
- while(!isalpha(fmt[i]))
- i++;
- switch(fmt[i])
- {
- case 's':
- strp=va_arg(ap,char*);
- if(width && width>strlen(strp))
- n+=width;
- else
- n+=strlen(strp);
- break;
- default:
- (void)va_arg(ap,void*);
- if(width && width>16)
- n+=width;
- else
- n+=16;
- }
- }
- va_end(ap);
- /* Allocate the string and vsprintf into it. */
- str=(char*)malloc(n);
- #ifdef __STDC__
- va_start(ap,fmt);
- #else
- va_start(ap);
- #endif
- n=vsprintf(str,fmt,ap);
- va_end(ap);
- /* Write the string. */
- n=write(fd,str,n);
- free(str);
- return(n);
- }