JD2022-TU1/main/extern/rfphio/rfp-srv/rfp.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();
}