bitchx/source/files.c

289 lines
5.3 KiB
C

/*
* files.c -- allows you to read/write files. Wow.
*
* (C) 1995 Jeremy Nelson (ESL)
* See the COPYRIGHT file for more information
*/
#include "irc.h"
static char cvsrevision[] = "$Id$";
CVS_REVISION(files_c)
#include "ircaux.h"
#define MAIN_SOURCE
#include "modval.h"
/* Here's the plan.
* You want to open a file.. you can READ it or you can WRITE it.
* unix files can be read/written, but its not the way you expect.
* so we will only alllow one or the other. If you try to write to
* read only file, it punts, and if you try to read a writable file,
* you get a null.
*
* New functions: open(FILENAME <type>)
* <type> is 0 for read, 1 for write, 0 is default.
* Returns fd of opened file, -1 on error
* read (fd)
* Returns line for given fd, as long as fd is
* opened via the open() call, -1 on error
* write (fd text)
* Writes the text to the file pointed to by fd.
* Returns the number of bytes written, -1 on error
* close (fd)
* closes file for given fd
* Returns 0 on OK, -1 on error
* eof (fd)
* Returns 1 if fd is at EOF, 0 if not. -1 on error
*/
struct FILE___ {
FILE *file;
struct FILE___ *next;
};
typedef struct FILE___ File;
static File *FtopEntry = NULL;
File *new_file (void)
{
File *tmp = FtopEntry;
File *tmpfile = (File *)new_malloc(sizeof(File));
if (FtopEntry == NULL)
FtopEntry = tmpfile;
else
{
while (tmp->next)
tmp = tmp->next;
tmp->next = tmpfile;
}
return tmpfile;
}
void remove_file (File *file)
{
File *tmp = FtopEntry;
if (file == FtopEntry)
FtopEntry = file->next;
else
{
while (tmp->next && tmp->next != file)
tmp = tmp->next;
if (tmp->next)
tmp->next = tmp->next->next;
}
fclose(file->file);
new_free((char **)&file);
}
int open_file_for_read (char *filename)
{
char *dummy_filename = NULL;
FILE *file;
malloc_strcpy(&dummy_filename, filename);
file = uzfopen(&dummy_filename, ".", 0);
new_free(&dummy_filename);
if (file)
{
File *nfs = new_file();
nfs->file = file;
nfs->next = NULL;
return fileno(file);
}
else
return -1;
}
int open_file_for_write (char *filename)
{
/* patch by Scott H Kilau so expand_twiddle works */
char *expand = NULL;
FILE *file;
if (!(expand = expand_twiddle(filename)))
malloc_strcpy(&expand, filename);
file = fopen(expand, "a");
new_free(&expand);
if (file)
{
File *nfs = new_file();
nfs->file = file;
nfs->next = NULL;
return fileno(file);
}
else
return -1;
}
int open_file_for_bwrite (char *filename)
{
/* patch by Scott H Kilau so expand_twiddle works */
char *expand = NULL;
FILE *file;
if (!(expand = expand_twiddle(filename)))
malloc_strcpy(&expand, filename);
file = fopen(expand, "wb");
new_free(&expand);
if (file)
{
File *nfs = new_file();
nfs->file = file;
nfs->next = NULL;
return fileno(file);
}
else
return -1;
}
File *lookup_file (int fd)
{
File *ptr = FtopEntry;
while (ptr)
{
if (fileno(ptr->file) == fd)
return ptr;
else
ptr = ptr -> next;
}
return NULL;
}
int file_write (int fd, char *stuff)
{
File *ptr = lookup_file(fd);
int ret;
if (!ptr)
return -1;
ret = fprintf(ptr->file, "%s\n", stuff);
fflush(ptr->file);
return ret;
}
int file_writeb (int fd, char *stuff)
{
File *ptr = lookup_file(fd);
int ret;
if (!ptr)
return -1;
ret = fwrite(stuff, 1, strlen(stuff), ptr->file);
fflush(ptr->file);
return ret;
}
char *file_read (int fd)
{
File *ptr = lookup_file(fd);
if (!ptr)
return m_strdup(empty_string);
else
{
char blah[10240];
if ((fgets(blah, 10239, ptr->file)))
chop(blah, 1);
else
blah[0] = 0;
return m_strdup(blah);
}
}
char *file_readb (int fd, int numb)
{
File *ptr = lookup_file(fd);
if (!ptr)
return m_strdup(empty_string);
else
{
char *blah = (char *)new_malloc(numb+1);
if ((fread(blah, 1, numb, ptr->file)))
blah[numb] = 0;
else
blah[0] = 0;
return blah;
}
}
int file_eof (int fd)
{
File *ptr = lookup_file (fd);
if (!ptr)
return -1;
else
return feof(ptr->file);
}
int file_close (int fd)
{
File *ptr = lookup_file (fd);
if (!ptr)
return -1;
else
remove_file (ptr);
return 0;
}
/*
** by: Walter Bright via Usenet C newsgroup
**
** modified by: Bob Stout based on a recommendation by Ray Gardner
**
** There is no point in going to asm to get high speed file copies. Since it
** is inherently disk-bound, there is no sense (unless tiny code size is
** the goal). Here's a C version that you'll find is as fast as any asm code
** for files larger than a few bytes (the trick is to use large disk buffers):
*/
int file_copy(int from,int to)
{
int bufsiz;
if (from < 0)
return 1;
if (to < 0)
return 1;
if (!fork())
{
/* Use the largest buffer we can get */
for (bufsiz = 0x4000; bufsiz >= 128; bufsiz >>= 1)
{
register char *buffer;
buffer = (char *) malloc(bufsiz);
if (buffer)
{
while (1)
{
register int n;
n = read(from,buffer,bufsiz);
if (n == -1) /* if error */
break;
if (n == 0) /* if end of file */
{
free(buffer);
_exit(0);
}
if (n != write(to,buffer,(unsigned) n))
break;
}
free(buffer);
break;
}
}
_exit(1);
}
return 0;
}
int file_valid (int fd)
{
if (lookup_file(fd))
return 1;
return 0;
}