557 lines
10 KiB
C
557 lines
10 KiB
C
#include <fcntl.h> /* Needed only for _O_RDWR definition */
|
|
#include <io.h>
|
|
#include <sys/stat.h>
|
|
#include <direct.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <assert.h>
|
|
|
|
//#include "main.h"
|
|
#include <revolution/types.h>
|
|
#include "typedefs.h"
|
|
|
|
#include "deci2.h"
|
|
#include "deci2hlp.h"
|
|
|
|
void MakeDeci2Hdr(DECI2_HDR *hdr, u_short l, u_short p, u_char s, u_char d);
|
|
|
|
#include "rfp.h"
|
|
#include "rfp-srv.h"
|
|
|
|
int rfp_verbose=1;
|
|
|
|
static char *hostname=NULL;
|
|
|
|
typedef struct {
|
|
char *name;
|
|
u_int fd;
|
|
int free;
|
|
} file_entry;
|
|
|
|
#define MAX_OPEN_FILES 20
|
|
|
|
file_entry file_table[MAX_OPEN_FILES];
|
|
|
|
int isActualFileSlot(file_entry*fe)
|
|
|
|
{
|
|
return (fe>=&file_table[0]) && (fe<&file_table[MAX_OPEN_FILES]);
|
|
}
|
|
|
|
void SetFileSlot(file_entry*fe, char *filename, int fd)
|
|
|
|
{
|
|
fe->fd = fd;
|
|
fe->name = strdup(filename);
|
|
fe->free = FALSE;
|
|
}
|
|
|
|
void FreeFileSlot(file_entry*fe)
|
|
|
|
{
|
|
fe->fd = (u_int)-1;
|
|
free(fe->name);
|
|
fe->name = NULL;
|
|
fe->free = TRUE;
|
|
}
|
|
|
|
void InitFileTable(void)
|
|
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<MAX_OPEN_FILES; i++) {
|
|
file_table[i].name=NULL;
|
|
file_table[i].fd=(u_int)-1;
|
|
file_table[i].free=TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
void ExitFileTable(void)
|
|
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<MAX_OPEN_FILES; i++) if(!file_table[i].free) {
|
|
close(file_table[i].fd);
|
|
FreeFileSlot(&file_table[i]);
|
|
}
|
|
|
|
}
|
|
|
|
int FindFreeFileSlot(void)
|
|
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<MAX_OPEN_FILES; i++)
|
|
if(file_table[i].free)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
int DoOpenFile(char *barefilename, int flags)
|
|
|
|
{
|
|
int fd;
|
|
int converted_flags;
|
|
char full_filename[0x100];
|
|
|
|
/* ignore mode bits */
|
|
|
|
converted_flags = (flags & 0x0000ffff) >> 1;
|
|
if((flags & DRFP_OPEN_RDWR) == DRFP_OPEN_RDWR) {
|
|
converted_flags &= ~ _O_WRONLY;
|
|
converted_flags |= _O_RDWR;
|
|
}
|
|
|
|
converted_flags |= _O_BINARY;
|
|
|
|
/* store files open for writing in a separate directory */
|
|
/* this directory must exist ! */
|
|
|
|
if((flags & DRFP_OPEN_WRONLY) && hostname) {
|
|
strcpy(full_filename, hostname);
|
|
strcat(full_filename, "/");
|
|
strcat(full_filename, barefilename);
|
|
} else
|
|
strcpy(full_filename, barefilename);
|
|
|
|
fd = _open (full_filename, converted_flags, _S_IREAD | _S_IWRITE);
|
|
|
|
if( fd != -1) {
|
|
int i;
|
|
i = FindFreeFileSlot();
|
|
SetFileSlot(&file_table[i], barefilename, fd);
|
|
return (int)(&file_table[i]);
|
|
|
|
} else {
|
|
if(rfp_verbose)
|
|
perror("file open failed:");
|
|
return -1;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
int DoCloseFile(int fd)
|
|
|
|
{
|
|
int ret;
|
|
file_entry*fe;
|
|
|
|
ret = -1;
|
|
|
|
fe=(file_entry*)fd;
|
|
|
|
if(!fe->free) {
|
|
int r;
|
|
r = _close(fe->fd);
|
|
if(r==0) {
|
|
FreeFileSlot(fe);
|
|
ret = 0;
|
|
} else {
|
|
}
|
|
} else {
|
|
;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int DoReadFile(int fd, unsigned int bytes, char *buffer)
|
|
|
|
{
|
|
int ret;
|
|
|
|
file_entry*fe;
|
|
|
|
ret = -1;
|
|
|
|
fe=(file_entry*)fd;
|
|
|
|
if(isActualFileSlot(fe) && !fe->free) {
|
|
ret = _read(fe->fd, buffer, bytes);
|
|
if(ret<0)
|
|
if(rfp_verbose)
|
|
perror( "Problem reading file" );
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
int DoWriteFile(int fd, unsigned int bytes, char *buffer)
|
|
|
|
{
|
|
int ret;
|
|
|
|
file_entry*fe;
|
|
|
|
ret = -1;
|
|
|
|
fe=(file_entry*)fd;
|
|
|
|
if(isActualFileSlot(fe) && !fe->free) {
|
|
// TrackFileWrittenTo(fe->name);
|
|
ret = _write(fe->fd, buffer, bytes);
|
|
if(ret<0)
|
|
if(rfp_verbose)
|
|
perror( "Problem writing file" );
|
|
} else
|
|
errno = EBADF;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
long DoSeekFile(int fd, int pos, int base)
|
|
|
|
{
|
|
long ret;
|
|
|
|
int converted_base;
|
|
|
|
file_entry*fe;
|
|
|
|
converted_base = 0;
|
|
|
|
switch(base) {
|
|
case 0:
|
|
converted_base = SEEK_SET;
|
|
break;
|
|
case 1:
|
|
converted_base = SEEK_CUR;
|
|
break;
|
|
case 2:
|
|
converted_base = SEEK_END;
|
|
break;
|
|
}
|
|
|
|
ret = -1L;
|
|
|
|
fe=(file_entry*)fd;
|
|
|
|
if(isActualFileSlot(fe) && !fe->free) {
|
|
ret = _lseek(fe->fd, pos, converted_base);
|
|
if(ret<0)
|
|
if(rfp_verbose)
|
|
perror( "Problem seeking pos in file" );
|
|
} else
|
|
errno = EBADF;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
void *RfpHandleOpen(DRFP_HDR *hdr)
|
|
|
|
{
|
|
int r;
|
|
|
|
struct _pkt {
|
|
DECI2_HDR deci2;
|
|
DRFP_HDR drfp;
|
|
DRFP_OPEN_R_BLOCK openR;
|
|
} *pkt;
|
|
|
|
DRFP_OPEN_BLOCK *blk = (DRFP_OPEN_BLOCK *)(hdr + 1);
|
|
M_bswapself32(blk->flag);
|
|
|
|
if(rfp_verbose)
|
|
printf("open file %s with flags %08x\n", blk->filename, blk->flag);
|
|
|
|
r = DoOpenFile(blk->filename, blk->flag);
|
|
|
|
|
|
if ((pkt=(struct _pkt *)GetBlock(sizeof(struct _pkt))) == NULL) return NULL;
|
|
|
|
MakeDeci2Hdr(&pkt->deci2, sizeof(struct _pkt), DECI2_PROTO_DRFP0,
|
|
DECI2_NODE_HOST, DECI2_NODE_IOP);
|
|
|
|
pkt->drfp.requestOrReplyCode = DRFP_CODE_OPENR;
|
|
pkt->drfp.requestSequenceNumber = hdr->requestSequenceNumber;
|
|
|
|
if(r!=-1) { // success
|
|
pkt->openR.fd = r;
|
|
pkt->openR.result = DRFP_OPENR_OKAY;
|
|
} else { // failure : don't distinguish ...
|
|
pkt->openR.fd = -1;
|
|
pkt->openR.result = DRFP_OPENR_ENOENT;
|
|
}
|
|
|
|
M_bswapself32(pkt->drfp.requestOrReplyCode);
|
|
M_bswapself32(pkt->drfp.requestSequenceNumber);
|
|
|
|
M_bswapself32(pkt->openR.fd);
|
|
M_bswapself32(pkt->openR.result);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
void *RfpHandleClose(DRFP_HDR *hdr)
|
|
|
|
{
|
|
int r;
|
|
|
|
struct _pkt {
|
|
DECI2_HDR deci2;
|
|
DRFP_HDR drfp;
|
|
DRFP_CLOSE_R_BLOCK closeR;
|
|
} *pkt;
|
|
|
|
DRFP_CLOSE_BLOCK *blk = (DRFP_CLOSE_BLOCK *)(hdr + 1);
|
|
M_bswapself32(blk->fd);
|
|
|
|
if(rfp_verbose)
|
|
printf("close file descriptor %08x\n", blk->fd);
|
|
|
|
r = DoCloseFile(blk->fd);
|
|
|
|
|
|
if ((pkt=(struct _pkt *)GetBlock(sizeof(struct _pkt))) == NULL) return NULL;
|
|
|
|
MakeDeci2Hdr(&pkt->deci2, sizeof(struct _pkt), DECI2_PROTO_DRFP0,
|
|
DECI2_NODE_HOST, DECI2_NODE_IOP);
|
|
|
|
pkt->drfp.requestOrReplyCode = DRFP_CODE_CLOSER;
|
|
pkt->drfp.requestSequenceNumber = hdr->requestSequenceNumber;
|
|
|
|
if(r==0) { // success
|
|
pkt->closeR.result = DRFP_CLOSER_OKAY;
|
|
} else { // failure : don't distinguish ...
|
|
pkt->closeR.result = DRFP_CLOSER_EBADF;
|
|
}
|
|
|
|
M_bswapself32(pkt->drfp.requestOrReplyCode);
|
|
M_bswapself32(pkt->drfp.requestSequenceNumber);
|
|
|
|
M_bswapself32(pkt->closeR.result);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
void *RfpHandleRead(DRFP_HDR *hdr)
|
|
|
|
{
|
|
int r;
|
|
int hdrsize;
|
|
int response_size;
|
|
|
|
struct _pkt {
|
|
DECI2_HDR deci2;
|
|
DRFP_HDR drfp;
|
|
DRFP_READ_R_BLOCK readR;
|
|
} *pkt;
|
|
|
|
DRFP_READ_BLOCK *blk = (DRFP_READ_BLOCK *)(hdr + 1);
|
|
M_bswapself32(blk->fd);
|
|
M_bswapself32(blk->numBytes);
|
|
|
|
if(rfp_verbose)
|
|
printf("read %d bytes from fd %08x\n", blk->numBytes, blk->fd);
|
|
|
|
/* allocate max possible packet for response */
|
|
hdrsize = sizeof(struct _pkt) /*- 1*/;
|
|
response_size = sizeof(struct _pkt) /*- 1*/ + blk->numBytes ;
|
|
|
|
assert(response_size <= DECI2_MAX_LEN);
|
|
|
|
if ((pkt=(struct _pkt *)GetBlock(response_size)) == NULL) return NULL;
|
|
|
|
r = DoReadFile(blk->fd, blk->numBytes, pkt->readR.data);
|
|
|
|
/* now that we now how much we read, set correct packet size in deci2 header */
|
|
MakeDeci2Hdr(&pkt->deci2,
|
|
r!=-1 ? (sizeof(struct _pkt) /*- 1*/ + r) : (sizeof(struct _pkt) /*- 1*/),
|
|
DECI2_PROTO_DRFP0, DECI2_NODE_HOST, DECI2_NODE_IOP);
|
|
|
|
pkt->drfp.requestOrReplyCode = DRFP_CODE_READR;
|
|
pkt->drfp.requestSequenceNumber = hdr->requestSequenceNumber;
|
|
|
|
if(r!=-1) {// success
|
|
pkt->readR.result = DRFP_READR_OKAY;
|
|
pkt->readR.numBytes = r;
|
|
} else { // failure : don't distinguish
|
|
pkt->readR.result = DRFP_READR_EIO;
|
|
pkt->readR.numBytes = 0;
|
|
}
|
|
|
|
M_bswapself32(pkt->drfp.requestOrReplyCode);
|
|
M_bswapself32(pkt->drfp.requestSequenceNumber);
|
|
|
|
M_bswapself32(pkt->readR.result);
|
|
M_bswapself32(pkt->readR.numBytes);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
void *RfpHandleWrite(DRFP_HDR *hdr)
|
|
|
|
{
|
|
int r;
|
|
|
|
struct _pkt {
|
|
DECI2_HDR deci2;
|
|
DRFP_HDR drfp;
|
|
DRFP_WRITE_R_BLOCK writeR;
|
|
} *pkt;
|
|
|
|
DRFP_WRITE_BLOCK *blk = (DRFP_WRITE_BLOCK *)(hdr + 1);
|
|
M_bswapself32(blk->fd);
|
|
M_bswapself32(blk->numBytes);
|
|
|
|
if(rfp_verbose)
|
|
printf("write %d bytes from fd %08x\n", blk->numBytes, blk->fd);
|
|
|
|
r = DoWriteFile(blk->fd, blk->numBytes, blk->data);
|
|
|
|
if ((pkt=(struct _pkt *)GetBlock(sizeof(struct _pkt))) == NULL) return NULL;
|
|
|
|
MakeDeci2Hdr(&pkt->deci2, sizeof(struct _pkt), DECI2_PROTO_DRFP0,
|
|
DECI2_NODE_HOST, DECI2_NODE_IOP);
|
|
|
|
pkt->drfp.requestOrReplyCode = DRFP_CODE_WRITER;
|
|
pkt->drfp.requestSequenceNumber = hdr->requestSequenceNumber;
|
|
|
|
if(!(r<0)) { // success
|
|
pkt->writeR.result = DRFP_WRITER_OKAY;
|
|
pkt->writeR.numBytes = r;
|
|
} else { // failure
|
|
switch(errno) {
|
|
case EBADF:
|
|
pkt->writeR.result = DRFP_WRITER_EBADF;
|
|
break;
|
|
case ENOSPC:
|
|
pkt->writeR.result = DRFP_WRITER_ENOSPC;
|
|
break;
|
|
default:
|
|
pkt->writeR.result = DRFP_WRITER_EIO;
|
|
break;
|
|
}
|
|
pkt->writeR.numBytes = 0;
|
|
}
|
|
|
|
M_bswapself32(pkt->drfp.requestOrReplyCode);
|
|
M_bswapself32(pkt->drfp.requestSequenceNumber);
|
|
|
|
M_bswapself32(pkt->writeR.numBytes);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
void *RfpHandleSeek(DRFP_HDR *hdr)
|
|
|
|
{
|
|
int r;
|
|
|
|
struct _pkt {
|
|
DECI2_HDR deci2;
|
|
DRFP_HDR drfp;
|
|
DRFP_SEEK_R_BLOCK seekR;
|
|
} *pkt;
|
|
|
|
DRFP_SEEK_BLOCK *blk = (DRFP_SEEK_BLOCK *)(hdr + 1);
|
|
M_bswapself32(blk->base);
|
|
M_bswapself32(blk->fd);
|
|
M_bswapself32(blk->offset);
|
|
|
|
if(rfp_verbose)
|
|
printf("seek pos %d/%d for fd %08x\n", blk->offset, blk->base, blk->fd);
|
|
|
|
r = DoSeekFile(blk->fd, blk->offset, blk->base);
|
|
|
|
|
|
if ((pkt=(struct _pkt *)GetBlock(sizeof(struct _pkt))) == NULL) return NULL;
|
|
|
|
MakeDeci2Hdr(&pkt->deci2, sizeof(struct _pkt), DECI2_PROTO_DRFP0,
|
|
DECI2_NODE_HOST, DECI2_NODE_IOP);
|
|
|
|
pkt->drfp.requestOrReplyCode = DRFP_CODE_SEEKR;
|
|
pkt->drfp.requestSequenceNumber = hdr->requestSequenceNumber;
|
|
|
|
if(r!=-1L) { // success
|
|
pkt->seekR.result = DRFP_SEEKR_OKAY;
|
|
pkt->seekR.filePos = r;
|
|
} else { // failure : don't distinguish ...
|
|
pkt->seekR.result = DRFP_SEEKR_EBADF;
|
|
pkt->seekR.filePos = 0;
|
|
}
|
|
|
|
M_bswapself32(pkt->drfp.requestOrReplyCode);
|
|
M_bswapself32(pkt->drfp.requestSequenceNumber);
|
|
|
|
M_bswapself32(pkt->seekR.result);
|
|
M_bswapself32(pkt->seekR.filePos);
|
|
|
|
return pkt;
|
|
}
|
|
|
|
void * RfpHandler(char *buf)
|
|
|
|
{
|
|
void *response;
|
|
|
|
DRFP_HDR *hdr = (DRFP_HDR *)buf;
|
|
|
|
M_bswapself32(hdr->requestOrReplyCode) ;
|
|
M_bswapself32(hdr->requestSequenceNumber) ;
|
|
|
|
|
|
switch(hdr->requestOrReplyCode) {
|
|
case DRFP_CODE_OPEN:
|
|
response = RfpHandleOpen(hdr);
|
|
break;
|
|
case DRFP_CODE_CLOSE:
|
|
response = RfpHandleClose(hdr);
|
|
break;
|
|
case DRFP_CODE_READ:
|
|
response = RfpHandleRead(hdr);
|
|
break;
|
|
case DRFP_CODE_WRITE:
|
|
response = RfpHandleWrite(hdr);
|
|
break;
|
|
case DRFP_CODE_SEEK:
|
|
response = RfpHandleSeek(hdr);
|
|
break;
|
|
default:
|
|
response = NULL;
|
|
printf("not ready for RFP message %d\n", hdr->requestOrReplyCode);
|
|
}
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
|
|
int CreateOutputDirectory(char *dirname)
|
|
|
|
{
|
|
int r;
|
|
|
|
if(dirname) {
|
|
r=_mkdir(dirname);
|
|
return 0;
|
|
} else
|
|
return -1;
|
|
}
|
|
|
|
void InitRFPClient(char *_hostname)
|
|
|
|
{
|
|
InitFileTable();
|
|
|
|
hostname = _hostname;
|
|
|
|
CreateOutputDirectory(hostname);
|
|
}
|
|
|
|
void ExitRFPClient(void)
|
|
|
|
{
|
|
ExitFileTable();
|
|
}
|