289 lines
5.3 KiB
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;
|
|
}
|
|
|