This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbcico/openfile.c
2005-08-28 11:34:24 +00:00

236 lines
6.6 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: Fidonet mailer
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/mbselib.h"
#include "config.h"
#include "lutil.h"
#include "openfile.h"
static FILE *infp=NULL;
static char *infpath=NULL;
static time_t intime;
static int isfreq;
char *freqname=NULL;
int gotfiles = FALSE;
extern char *tempinbound;
/*
* Try to find present (probably incomplete) file with the same timestamp
* (it might be renamed), open it for append and store resync offset.
* Store 0 in resync offset if the file is new. Return FILE* or NULL.
* resync() must accept offset in bytes and return 0 on success, nonzero
* otherwise (and then the file will be open for write). For Zmodem,
* resync is always possible, but for SEAlink it is not. Do not try
* any resyncs if remsize == 0.
*/
FILE *openfile(char *fname, time_t remtime, off_t remsize, off_t *resofs, int(*resync)(off_t))
{
char *opentype, *p, x, ctt[32], tmpfname[16];
int rc, rsc, ncount;
struct stat st;
strcpy(ctt,date(remtime));
Syslog('s', "openfile(\"%s\",%s,%lu,...)", MBSE_SS(fname), MBSE_SS(ctt), (unsigned long)remsize);
if ((fname == NULL) || (fname[0] == '\0')) {
snprintf(tmpfname,15,"%08lx.pkt",(unsigned long)sequencer());
fname=tmpfname;
}
if ((strlen(fname) == 12) && (strspn(fname,"0123456789abcdefABCDEF") == 8) && (strcasecmp(fname+8,".req") == 0)) {
Syslog('s', "Received wazoo freq file");
isfreq = TRUE;
} else
isfreq = FALSE;
/*
* First check if the file is already in the inbound directory.
* If it's there, resoffs will be set equal to remsize to signal the
* receiving protocol to skip the file.
*/
if (tempinbound == NULL) {
/*
* This is when we get a FTS-0001 handshake packet
*/
infpath = xstrcpy(CFG.inbound);
infpath = xstrcat(infpath, (char *)"/tmp/");
mkdirs(infpath, 0700);
} else {
infpath = xstrcpy(tempinbound);
infpath = xstrcat(infpath, (char *)"/");
}
infpath = xstrcat(infpath, fname);
if (stat(infpath, &st) == 0) {
Syslog('s', "remtine=%ld, st_time=%ld, remsize=%ld, st_size=%ld", remtime, st.st_mtime, remsize, st.st_size);
if ((remtime == st.st_mtime) && (remsize == st.st_size)) {
Syslog('+', "File %s is already here", fname);
*resofs = st.st_size;
free(infpath);
infpath = NULL;
return NULL;
}
}
/*
* If the file is in the inbound with a zero length, erase the
* file as if it wasn't there at all.
*/
if (((rc = stat(infpath, &st)) == 0) && (st.st_size == 0)) {
Syslog('+', "Zero bytes file in the inbound, unlinking");
unlink(infpath);
}
/*
* If the file is not already in the inbound, but there is a file
* with the same name, the new file will be renamed if the file
* has another timestamp as the file we expect.
*
* Renaming algorythm is as follows: start with the present name,
* increase the last character of the file name, jumping from
* '9' to 'a', from 'z' to 'A', from 'Z' to '0'. If _all_ these
* names are occupied, create random name.
*/
p = infpath + strlen(infpath) -1;
x = *p;
ncount = 0;
while (((rc = stat(infpath, &st)) == 0) && (remtime != st.st_mtime) && (ncount++ < 62)) {
if (x == '9')
x = 'a';
else if (x == 'z')
x = 'A';
else if (x == 'Z')
x = '0';
else
x++;
*p = x;
}
if (ncount >= 62) { /* names exhausted */
rc = 1;
p = strrchr(infpath,'/');
*p = '\0';
snprintf(ctt,31,"%08lx.doe",(unsigned long)sequencer());
free(infpath);
infpath = xstrcpy(p);
infpath = xstrcat(infpath, ctt);
}
if (ncount)
Syslog('s', "File renamed to %s", infpath);
*resofs = 0L;
opentype = (char *)"w";
if ((rc == 0) && (remsize != 0)) {
rsc = resync(st.st_size);
Syslog('s', "resync(%d) rsc=%d", (int)st.st_size, rsc);
switch (rsc) {
case 0: /* Success */
opentype = (char *)"a+";
*resofs = st.st_size;
Syslog('+', "Resyncing at offset %lu of \"%s\"", (unsigned long)st.st_size, infpath);
break;
case -1: /* Binkp did send a GET, return here and do not open file */
free(infpath);
infpath = NULL;
return NULL;
default: /* Error from xmrecv, do nothing */
break;
}
}
Syslog('s', "try fopen(\"%s\",\"%s\")", infpath, opentype);
if ((infp = fopen(infpath, opentype)) == NULL) {
WriteError("$Cannot open local file \"%s\" for \"%s\"", infpath,opentype);
free(infpath);
infpath=NULL;
return NULL;
}
intime = remtime;
if (isfreq) {
if (freqname)
free(freqname);
freqname = xstrcpy(infpath);
}
Syslog('s', "opened file \"%s\" for \"%s\", restart at %lu", infpath,opentype,(unsigned long)*resofs);
return infp;
}
/*
* close file, even if the file is partial received, we set the date on the
* file so that in a next session we know we must append to that file instead of
* trying to get the file again.
*/
int closefile(void)
{
int rc = 0;
struct utimbuf ut;
Syslog('s', "closefile(), for file \"%s\"", MBSE_SS(infpath));
if ((infp == NULL) || (infpath == NULL)) {
Syslog('+', "closefile(), nothing to close");
return 1;
}
rc = fclose(infp);
infp = NULL;
if (rc == 0) {
ut.actime = intime;
ut.modtime = intime;
if ((rc = utime(infpath,&ut)))
WriteError("$utime failed");
}
if (isfreq) {
if (rc != 0) {
Syslog('+', "Removing unsuccessfuly received wazoo freq");
unlink(freqname);
free(freqname);
freqname=NULL;
}
isfreq = FALSE;
}
free(infpath);
infpath = NULL;
return rc;
}