236 lines
6.5 KiB
C
236 lines
6.5 KiB
C
/*****************************************************************************
|
|
*
|
|
* $Id$
|
|
* Purpose ...............: Fidonet mailer
|
|
*
|
|
*****************************************************************************
|
|
* Copyright (C) 1997-2008
|
|
*
|
|
* 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), ctt, (unsigned int)remsize);
|
|
|
|
if ((fname == NULL) || (fname[0] == '\0')) {
|
|
snprintf(tmpfname,16,"%08x.pkt",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,32,"%08x.doe",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 int)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 int)*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;
|
|
}
|
|
|
|
|