/* @@@HEAD@@@
// Connection and File I/O module
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include "defs.h"
#include "y.tab.h"
#include "operators.h"
#include "execute.h"
#include "cdc_types.h"
#include "memory.h"
#include "util.h"
/*
// Initialize a file path, make sure you can open it, etc
//
// return values:
//
// 0 if it failed and threw an error
// 1 if everything is O.K.
//
// Added: 30 Jul 95 - BJG
*/
internal int init_file_path(data_t * name,
struct stat * statbuf,
char * fname,
int max)
{
int len;
len = string_length(name->u.str);
if (strstr(string_chars(name->u.str), "../") || len == 0) {
cthrow(perm_id, "Filename %D is not legal.", name);
return 0;
}
/* create a variable it will pull the base name from */
strncpy(fname, "root/", max);
strncat(fname, string_chars(name->u.str), max);
/* Stat the file */
if (stat(fname, statbuf) < 0) {
cthrow(file_id, "Cannot find file %D.", name);
return 0;
}
if (S_ISDIR(statbuf->st_mode)) {
cthrow(directory_id, "File %D is a directory.", name);
return 0;
}
return 1;
}
/*
// Get basic statistics on a file
//
// Added: 30 Jul 95 - BJG
*/
void op_stat_file(void) {
struct stat sbuf;
register int x;
list_t * s;
data_t * args,
* d;
char fname[BIGBUF];
if (!func_init_1(&args, STRING))
return;
if (!init_file_path(&args[0], &sbuf, fname, BIGBUF)) {
return;
}
s = list_new(5);
d = list_empty_spaces(s, 5);
for (x=0; x < 5; x++)
d[x].type = INTEGER;
d[0].u.val = (int) sbuf.st_mode;
d[1].u.val = (int) sbuf.st_size;
d[2].u.val = (int) sbuf.st_atime;
d[3].u.val = (int) sbuf.st_mtime;
d[4].u.val = (int) sbuf.st_ctime;
push_list(s);
list_discard(s);
}
/*
// Read a file into the db
//
// Added: 30 Jul 95 - BJG
*/
void op_read_file(void)
{
size_t size, i, r;
data_t *args;
FILE *fp;
char fname[BIGBUF];
Buffer *buf;
struct stat statbuf;
/* Accept the name of a file to read */
if (!func_init_1(&args, STRING))
return;
if (!init_file_path(&args[0], &statbuf, fname, BIGBUF)) {
return;
}
size = statbuf.st_size;
/* Open the file for reading. */
fp = open_scratch_file(fname, "r");
pop(1);
if (!fp) {
cthrow(file_id, "Cannot open file %D for reading.", &args[0]);
return;
}
/* Allocate a buffer to hold the file contents. */
buf = buffer_new(size);
/* Read in the file. */
i = 0;
while (i < size) {
r = fread(buf->s + i, sizeof(unsigned char), size, fp);
if (r <= 0) {
buffer_discard(buf);
close_scratch_file(fp);
cthrow(file_id, "Trouble reading file %D.", &args[0]);
return;
}
i += r;
}
/* return the buffer (wahoo, big memory chunks) */
push_buffer(buf);
/* Discard the buffer and close the file. */
buffer_discard(buf);
close_scratch_file(fp);
}
/*
// echo a file to the connection
*/
void op_echo_file(void)
{
size_t size, i, r;
data_t *args;
FILE *fp;
char fname[BIGBUF];
Buffer *buf;
struct stat statbuf;
/* Accept the name of a file to echo. */
if (!func_init_1(&args, STRING))
return;
/* Initialize the file */
if (!init_file_path(&args[0], &statbuf, fname, BIGBUF)) {
return;
}
pop(1);
size = statbuf.st_size;
/* Open the file for reading. */
fp = open_scratch_file(fname, "r");
if (!fp) {
cthrow(file_id, "Cannot open file %D for reading.", &args[0]);
return;
}
/* Allocate a buffer to hold the file contents. */
buf = buffer_new(size);
/* Read in the file. */
i = 0;
while (i < size) {
r = fread(buf->s + i, sizeof(unsigned char), size, fp);
if (r <= 0) {
buffer_discard(buf);
close_scratch_file(fp);
cthrow(file_id, "Trouble reading file %D.", &args[0]);
return;
}
i += r;
}
/* Write the file. */
tell(cur_frame->object->dbref, buf);
/* Discard the buffer and close the file. */
buffer_discard(buf);
close_scratch_file(fp);
push_int(1);
}