/* $Id: input.c,v 1.13 2001/02/10 03:40:03 harbourn Exp $
*Input handeling module for fatback
* (c)2000-2001 DoD Computer Forensics Lab
* By SrA Nicholas Harbour
*/
/* The purpose of this module is to provide a layer of abstraction for
the program to get input from.
*/
#include <stdio.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "input.h"
static FILE *Input_stream;
static int Input_fd;
static caddr_t Mem_ptr; /* for mmap() objects as input */
static struct stat File_stat;
static int Mmap_fd;
static input_t Input_type;
/* input_ops functions for descriptor based input type */
static int dfile_init(va_list);
static size_t dfile_read(caddr_t, off_t, size_t);
static void dfile_close(void);
/* input_ops functions for RFILE input type */
static int rfile_init(va_list);
static size_t rfile_read(caddr_t, off_t, size_t);
static void rfile_close(void);
#ifdef HAVE_MMAP
/* input_ops functions for MMAP input type */
static int mmap_init(va_list);
static size_t mmap_read(caddr_t, off_t, size_t);
static void mmap_close(void);
#endif /*HAVE_MMAP*/
/*
* Each type of input must provide three basic funcions,
* initialize, read, and close. this structure contains
* pointers to those functions.
*/
struct input_ops_s {
int (*i_init)(va_list);
size_t (*i_read)(caddr_t, off_t, size_t);
void (*i_close)(void);
};
/*
* Each supported input type must add a structure
* to this array. The fields are function pointers
* as described by the input_ops_s structure.
*/
struct input_ops_s input_ops[] = {
{ /* DFILE */
dfile_init,
dfile_read,
dfile_close
},
{ /* RFILE */
rfile_init,
rfile_read,
rfile_close
}
#ifdef HAVE_MMAP
,{ /* MMAP */
mmap_init,
mmap_read,
mmap_close
}
#endif /*HAVE_MMAP*/
};
/*
* Initialize the input based on the type.
* This function calls the appropriate function
* based on the input type specified.
*/
int input_init(input_t type, ...)
{
va_list arg_list;
va_start(arg_list, type);
Input_type = type;
if ((INPUT_T_MIN <= Input_type) && (Input_type <= INPUT_T_MAX))
if ((*input_ops[Input_type].i_init)(arg_list)) {
va_end(arg_list);
return 0;
}
va_end(arg_list);
return -1;
}
/*
* This is the user level interface to read
* data from the input. This calls the appropriate
* function based on the input type.
*/
size_t read_data(caddr_t ptr, off_t offset, size_t size)
{
if (!size || !ptr)
return 0;
return (*input_ops[Input_type].i_read)(ptr, offset, size);
}
/*
* This is the user level interface to close
* the input. It calls the appropriate close
* function based on the input type.
*/
void input_close(void)
{
(*input_ops[Input_type].i_close)();
}
/*
* Initialize function for descriptor based
* file io.
*/
static int dfile_init(va_list arg_list)
{
char *filename = va_arg(arg_list, char *);
if (!filename)
return 0;
errno = 0;
stat(filename, &File_stat);
if (errno) {
perror("Error in dfile_init()");
return 0;
}
Input_fd = open(filename, O_RDONLY);
if (errno) {
perror("Error in dfile_init()");
return 0;
}
return 1;
}
/*
* Read data from a file discriptor
*/
static size_t dfile_read(caddr_t ptr, off_t offset, size_t size)
{
size_t retval;
errno = 0;
lseek(Input_fd, offset, SEEK_SET);
if (errno) {
perror("Error in dfile_read()1");
return 0;
}
retval = read(Input_fd, ptr, size);
if (errno) {
perror("Error in dfile_read()2");
return 0;
}
return retval;
}
/*
* Close a file descriptor
*/
static void dfile_close(void)
{
close(Input_fd);
}
/*
* Initialize function for regular files.
* uses streams input.
*/
static int rfile_init(va_list arg_list)
{
char *filename = va_arg(arg_list, char *);
if (!filename)
return 0;
errno = 0;
stat(filename, &File_stat);
if (errno) {
perror("Error in rfile_init()");
return 0;
}
Input_stream = fopen(filename, "r");
if (!Input_stream) {
perror("Error in rfile_init()");
return 0;
} else
return 1;
}
/*
* Read data from a regular file or stream.
*/
static size_t rfile_read(caddr_t ptr, off_t offset, size_t size)
{
size_t retval;
errno = 0;
if (fseek(Input_stream, offset, SEEK_SET)) {
perror("Error in rfile_read()");
return 0;
}
else
if (!(retval = fread(ptr, 1, size, Input_stream))) {
perror("Error in rfile_read()");
return 0;
}
return retval;
}
/*
* Close a regular file
*/
static void rfile_close(void)
{
fclose(Input_stream);
}
#ifdef HAVE_MMAP
/*
* Initialize function for MMAP input
* type.
*/
static int mmap_init(va_list arg_list)
{
char *filename = va_arg(arg_list, char *);
if (!filename)
return 0;
errno = 0;
stat(filename, &File_stat);
if (errno) {
perror("Error in mmap_init()");
return 0;
}
if (!(Mmap_fd = open(filename, O_RDONLY)))
return 0;
Mem_ptr = mmap(NULL, File_stat.st_size, PROT_READ, MAP_SHARED, Mmap_fd, 0);
if (!Mem_ptr) {
perror("Error in mmap_init()");
return 0;
} else
return 1;
}
/*
* Read data from an MMAP input type
*/
static size_t mmap_read(caddr_t ptr, off_t offset, size_t size)
{
if (offset + size > File_stat.st_size)
return 0;
if (!memcpy(ptr, Mem_ptr + offset, size)) {
perror("Error in mmap_read()");
return 0;
}
return size;
}
/*
* Close funcion for MMAP input type
*/
static void mmap_close(void)
{
munmap(Mem_ptr, File_stat.st_size);
close(Mmap_fd);
}
#endif /*HAVE_MMAP*/
syntax highlighted by Code2HTML, v. 0.9.1