diff --git a/mbfido/Makefile b/mbfido/Makefile index f0c80704..fce6641a 100644 --- a/mbfido/Makefile +++ b/mbfido/Makefile @@ -11,7 +11,8 @@ SRCS = addbbs.c backalias.c flock.c hatch.c mbdiff.c mgrutil.c pack.c \ utic.c announce.c fflist.c ftn2rfc.c makestat.c mbindex.c msgutil.c \ postecho.c rollover.c tic.c areamgr.c filefind.c grlist.c maketags.c \ mbmsg.c newspost.c postemail.c scan.c toberep.c atoul.c filemgr.c \ - hash.c mbaff.c mbseq.c notify.c postnetmail.c scannews.c tosspkt.c + hash.c mbaff.c mbseq.c notify.c postnetmail.c scannews.c tosspkt.c \ + mbfkill.c mbfutil.c mbfindex.c mbfcheck.c mbfpack.c mbflist.c mbfadopt.c HDRS = addbbs.h backalias.h flock.h hatch.h mbdiff.h mgrutil.h pack.h \ postnetmail.h scannews.h tosspkt.h addpkt.h bwrite.h forward.h \ lhash.h mbfido.h mkftnhdr.h paths.h ptic.h sendmail.h tracker.h \ @@ -19,7 +20,8 @@ HDRS = addbbs.h backalias.h flock.h hatch.h mbdiff.h mgrutil.h pack.h \ storeecho.h ulock.h announce.h fflist.h ftn2rfc.h makestat.h mbindex.h \ msgutil.h post.h rnews.h storenet.h utic.h areamgr.h filefind.h \ grlist.h maketags.h mbmsg.h newspost.h postecho.h rollover.h tic.h \ - atoul.h filemgr.h hash.h mbaff.h mbseq.h notify.h postemail.h scan.h toberep.h + atoul.h filemgr.h hash.h mbaff.h mbseq.h notify.h postemail.h scan.h toberep.h \ + mbfkill.h mbfutil.h mbfindex.h mbfcheck.h mbfpack.h mbflist.h mbfadopt.h MBFIDO_OBJS = flock.o tosspkt.o mbfido.o hatch.o maketags.o \ tracker.o makestat.o scannews.o lhash.o \ pack.o ulock.o tic.o ptic.o utic.o mover.o hash.o mkftnhdr.o \ @@ -31,7 +33,7 @@ MBSEQ_OBJS = mbseq.o MBAFF_OBJS = announce.o fflist.o filefind.o grlist.o mbaff.o msgutil.o MBINDEX_OBJS = mbindex.o MBDIFF_OBJS = mbdiff.o -MBFILE_OBJS = mbfile.o +MBFILE_OBJS = mbfile.o mbfkill.o mbfutil.o mbfindex.o mbfcheck.o mbfpack.o mbflist.o mbfadopt.o MBMSG_OBJS = post.o mbmsg.o MBFIDO_LIBS = ../lib/libmemwatch.a ../lib/libclcomm.a ../lib/libcommon.a ../lib/libmsgbase.a \ ../lib/libdbase.a ../lib/libmbinet.a @@ -149,7 +151,7 @@ aliasdb.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../li cookie.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h cookie.h fsort.o: ../lib/libs.h ../lib/clcomm.h fsort.h magic.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbtic.h tic.h utic.h magic.h -mbfile.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfile.h +mbfile.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfkill.h mbfindex.h mbfcheck.h mbfpack.h mbflist.h mbfutil.h mbfile.h mover.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h tic.h mover.h post.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h ../lib/msg.h ../lib/msgtext.h post.h rnews.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/mbinet.h ../lib/dbdupe.h ../lib/dbnode.h ../lib/dbmsgs.h ../lib/msg.h ../lib/msgtext.h pack.h rfc2ftn.h mbfido.h paths.h rnews.h @@ -182,4 +184,10 @@ notify.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib postnetmail.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/dbcfg.h ../lib/dbuser.h ../lib/dbnode.h ../lib/dbftn.h ../lib/common.h ../lib/clcomm.h tracker.h addpkt.h storenet.h ftn2rfc.h areamgr.h filemgr.h ping.h postemail.h scannews.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/mbinet.h ../lib/dbdupe.h ../lib/dbnode.h ../lib/dbmsgs.h ../lib/msg.h ../lib/msgtext.h mkftnhdr.h hash.h rollover.h pack.h storeecho.h rfc2ftn.h scannews.h tosspkt.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/msg.h ../lib/msgtext.h ../lib/dbcfg.h ../lib/dbnode.h ../lib/dbmsgs.h ../lib/dbdupe.h ../lib/dbuser.h ../lib/dbftn.h tosspkt.h postnetmail.h postecho.h rollover.h +mbfkill.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfkill.h mbfutil.h +mbfutil.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfutil.h mbfile.h +mbfindex.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfutil.h mbfindex.h +mbfcheck.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfutil.h mbfcheck.h +mbfpack.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfutil.h mbfpack.h +mbflist.o: ../lib/libs.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h ../lib/dbcfg.h mbfutil.h mbflist.h # End of generated dependencies diff --git a/mbfido/mbfadopt.c b/mbfido/mbfadopt.c new file mode 100644 index 00000000..9da83a55 --- /dev/null +++ b/mbfido/mbfadopt.c @@ -0,0 +1,253 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - Adopt file + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbflist.h" + + + +extern int do_quiet; /* Supress screen output */ + + + +void AdoptFile(int Area, char *File, char *Description) +{ + FILE *pAreas, *pFile, *fp; + char *sAreas, *fAreas, *temp, *temp2, *unarc, *cmd, *pwd; + int IsArchive = FALSE, MustRearc = FALSE, UnPacked = FALSE; + int IsVirus = FALSE, File_Id = FALSE; + + Syslog('-', "Adopt(%d, %s, %s)", Area, MBSE_SS(File), MBSE_SS(Description)); + + if (!do_quiet) + colour(CYAN, BLACK); + + sAreas = calloc(PATH_MAX, sizeof(char)); + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("$Can't open %s", sAreas); + if (!do_quiet) + printf("Can't open %s\n", sAreas); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + if (fseek(pAreas, ((Area - 1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET)) { + WriteError("$Can't seek record %d in %s", Area, sAreas); + if (!do_quiet) + printf("Can't seek record %d in %s\n", Area, sAreas); + fclose(pAreas); + free(sAreas); + die(0); + } + + if (fread(&area, areahdr.recsize, 1, pAreas) != 1) { + WriteError("$Can't read record %d in %s", Area, sAreas); + if (!do_quiet) + printf("Can't read record %d in %s\n", Area, sAreas); + fclose(pAreas); + free(sAreas); + die(0); + } + + if (area.Available) { + fAreas = calloc(PATH_MAX, sizeof(char)); + temp = calloc(PATH_MAX, sizeof(char)); + pwd = calloc(PATH_MAX, sizeof(char)); + + sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), Area); + getcwd(pwd, PATH_MAX); + + /* + * Open the file database, create new one if it doesn't excist. + */ + if ((pFile = fopen(fAreas, "r+")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + if (!do_quiet) { + printf("Adopt file: %s ", File); + printf("Unpacking \b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + } + + if ((unarc = unpacker(File)) == NULL) + Syslog('+', "Unknown archive format %s", File); + else { + IsArchive = TRUE; + if (strlen(area.Archiver) && (strcmp(unarc, area.Archiver) == 0)) + MustRearc = TRUE; + } + + if (IsArchive) { + /* + * Check if there is a temp directory to unpack the archive. + */ + sprintf(temp, "%s/tmp/arc", getenv("MBSE_ROOT")); + if ((access(temp, R_OK)) != 0) { + if (mkdir(temp, 0777)) { + WriteError("$Can't create %s", temp); + if (!do_quiet) + printf("Can't create %s\n", temp); + die(0); + } + } + + /* + * Check for stale FILE_ID.DIZ files + */ + sprintf(temp, "%s/tmp/arc/FILE_ID.DIZ", getenv("MBSE_ROOT")); + if (!unlink(temp)) + Syslog('+', "Removed stale %s", temp); + sprintf(temp, "%s/tmp/arc/file_id.diz", getenv("MBSE_ROOT")); + if (!unlink(temp)) + Syslog('+', "Removed stale %s", temp); + + if (!getarchiver(unarc)) { + WriteError("No archiver available for %s", File); + if (!do_quiet) + printf("No archiver available for %s\n", File); + die(0); + } + + cmd = xstrcpy(archiver.funarc); + if ((cmd == NULL) || (cmd == "")) { + WriteError("No unarc command available"); + if (!do_quiet) + printf("No unarc command available\n"); + die(0); + } + + sprintf(temp, "%s/tmp/arc", getenv("MBSE_ROOT")); + if (chdir(temp) != 0) { + WriteError("$Can't change to %s", temp); + die(0); + } + + sprintf(temp, "%s/%s", pwd, File); + if (execute(cmd, temp, (char *)NULL, (char *)"/dev/null", (char *)"/dev/null", (char *)"/dev/null") == 0) { + UnPacked = TRUE; + } else { + chdir(pwd); + WriteError("Unpack error, file may be corrupt"); + DeleteVirusWork(); + die(0); + } + + if (!do_quiet) { + printf("Virscan \b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + } + sprintf(temp, "%s/etc/virscan.data", getenv("MBSE_ROOT")); + + if ((fp = fopen(temp, "r")) == NULL) { + WriteError("No virus scanners defined"); + } else { + fread(&virscanhdr, sizeof(virscanhdr), 1, fp); + + while (fread(&virscan, virscanhdr.recsize, 1, fp) == 1) { + cmd = NULL; + if (virscan.available) { + cmd = xstrcpy(virscan.scanner); + cmd = xstrcat(cmd, (char *)" "); + cmd = xstrcat(cmd, virscan.options); + if (execute(cmd, (char *)"*", (char *)NULL, (char *)"/dev/null", + (char *)"/dev/null", (char *)"/dev/null") != virscan.error) { + WriteError("Virus found by %s", virscan.comment); + IsVirus = TRUE; + } + free(cmd); + } + } + fclose(fp); + + if (IsVirus) { + DeleteVirusWork(); + chdir(pwd); + WriteError("Virus found"); + if (!do_quiet) + printf("Virus found\n"); + die(0); + } + } + + if (!do_quiet) { + printf("Checking \b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + } + + temp2 = calloc(PATH_MAX, sizeof(char)); + sprintf(temp, "%s/tmp/arc/FILE_ID.DIZ", getenv("MBSE_ROOT")); + sprintf(temp2, "%s/tmp/FILE_ID.DIZ", getenv("MBSE_ROOT")); + if (file_cp(temp, temp2) == 0) { + File_Id = TRUE; + } else { + sprintf(temp, "%s/tmp/arc/file_id.diz", getenv("MBSE_ROOT")); + if (file_cp(temp, temp2) == 0) + File_Id = TRUE; + } + free(temp2); + if (File_Id) + Syslog('-', "FILE_ID.DIZ found"); + + + DeleteVirusWork(); + fclose(pFile); + } + + free(pwd); + free(temp); + free(fAreas); + } else { + WriteError("Area %d is not available", Area); + if (!do_quiet) + printf("Area %d is not available\n", Area); + } + + fclose(pAreas); + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(sAreas); +} + diff --git a/mbfido/mbfadopt.h b/mbfido/mbfadopt.h new file mode 100644 index 00000000..e6db4777 --- /dev/null +++ b/mbfido/mbfadopt.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFADOPT_H_ +#define _MBFADOPT_H + +void AdoptFile(int, char *, char *); + +#endif diff --git a/mbfido/mbfcheck.c b/mbfido/mbfcheck.c new file mode 100644 index 00000000..b288b8ca --- /dev/null +++ b/mbfido/mbfcheck.c @@ -0,0 +1,247 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - Check filebase + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbfcheck.h" + + + +extern int do_quiet; /* Supress screen output */ +extern int do_pack; /* Pack filebase */ + + + +/* + * Check file database integrity, all files in the file database must + * exist in real, the size and date/time must match, the files crc is + * checked, and if anything is wrong, the file database is updated. + * If the file is missing the entry is marked as deleted. With the + * pack option that record will be removed. + * After these checks, de database is checked for missing records, if + * there are files on disk but not in the directory these files are + * deleted. System files (beginning with a dot) are left alone and + * the files 'files.bbs', 'files.bak', '00index', 'header' 'readme' + * and 'index.html' too. + * + * Remarks: Maybe if the crc check fails, and the date and time are + * ok, the file is damaged and must be made unavailable. + */ +void Check(void) +{ + FILE *pAreas, *pFile; + int i, iAreas, iAreasNew = 0; + int iTotal = 0, iErrors = 0; + char *sAreas, *fAreas, *newdir; + DIR *dp; + struct dirent *de; + int Found, Update; + char fn[PATH_MAX]; + struct stat stb; + + sAreas = calloc(PATH_MAX, sizeof(char)); + fAreas = calloc(PATH_MAX, sizeof(char)); + newdir = calloc(PATH_MAX, sizeof(char)); + + if (!do_quiet) { + colour(3, 0); + printf("Checking file database...\n"); + } + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("Can't open %s", sAreas); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + fseek(pAreas, 0, SEEK_END); + iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; + + for (i = 1; i <= iAreas; i++) { + + fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&area, areahdr.recsize, 1, pAreas); + + if (area.Available) { + + IsDoing("Check area %d", i); + + if (!do_quiet) { + printf("\r%4d => %-44s \b\b\b\b", i, area.Name); + fflush(stdout); + } + + /* + * Check if download directory exists, + * if not, create the directory. + */ + if (access(area.Path, R_OK) == -1) { + Syslog('!', "No dir: %s", area.Path); + sprintf(newdir, "%s/foobar", area.Path); + mkdirs(newdir); + } + + sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); + + /* + * Open the file database, if it doesn't exist, + * create an empty one. + */ + if ((pFile = fopen(fAreas, "r+")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + /* + * Now start checking the files in the filedatabase + * against the contents of the directory. + */ + while (fread(&file, sizeof(file), 1, pFile) == 1) { + + iTotal++; + sprintf(newdir, "%s/%s", area.Path, file.Name); + + if (file_exist(newdir, R_OK)) { + Syslog('+', "File %s area %d not on disk.", newdir, i); + if (!file.NoKill) { + file.Deleted = TRUE; + do_pack = TRUE; + } + iErrors++; + file.Missing = TRUE; + fseek(pFile, - sizeof(file), SEEK_CUR); + fwrite(&file, sizeof(file), 1, pFile); + } else { + /* + * File exists, now check the file. + */ + Marker(); + Update = FALSE; + if (file_time(newdir) != file.FileDate) { + Syslog('!', "Date mismatch area %d file %s", i, file.Name); + file.FileDate = file_time(newdir); + iErrors++; + Update = TRUE; + } + if (file_size(newdir) != file.Size) { + Syslog('!', "Size mismatch area %d file %s", i, file.Name); + file.Size = file_size(newdir); + iErrors++; + Update = TRUE; + } + if (file_crc(newdir, CFG.slow_util && do_quiet) != file.Crc32) { + Syslog('!', "CRC error area %d, file %s", i, file.Name); + file.Crc32 = file_crc(newdir, CFG.slow_util && do_quiet); + iErrors++; + Update = TRUE; + } + Marker(); + if (Update) { + fseek(pFile, - sizeof(file), SEEK_CUR); + fwrite(&file, sizeof(file), 1, pFile); + } + } + } + + /* + * Check files in the directory against the database. + * This test is skipped for CD-rom. + */ + if (!area.CDrom) { + if ((dp = opendir(area.Path)) != NULL) { + while ((de = readdir(dp)) != NULL) { + if (de->d_name[0] != '.') { + Marker(); + Found = FALSE; + rewind(pFile); + while (fread(&file, sizeof(file), 1, pFile) == 1) { + if (strcmp(file.Name, de->d_name) == 0) { + Found = TRUE; + break; + } + } + if ((!Found) && + (strncmp(de->d_name, "files.bbs", 9)) && + (strncmp(de->d_name, "files.bak", 9)) && + (strncmp(de->d_name, "00index", 7)) && + (strncmp(de->d_name, "header", 6)) && + (strncmp(de->d_name, "index", 5)) && + (strncmp(de->d_name, "readme", 6))) { + sprintf(fn, "%s/%s", area.Path, de->d_name); + if (stat(fn, &stb) == 0) + if (S_ISREG(stb.st_mode)) { + if (unlink(fn) == 0) { + Syslog('!', "%s not in fdb, deleted from disk", fn); + iErrors++; + } else { + WriteError("$%s not in fdb, cannot delete", fn); + } + } + } + } + } + closedir(dp); + } else { + WriteError("Can't open %s", area.Path); + } + } + + fclose(pFile); + chmod(fAreas, 0660); + iAreasNew++; + + } /* if area.Available */ + } + + fclose(pAreas); + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(newdir); + free(sAreas); + free(fAreas); + + Syslog('+', "Check Areas [%5d] Files [%5d] Errors [%5d]", iAreasNew, iTotal, iErrors); +} + + + diff --git a/mbfido/mbfcheck.h b/mbfido/mbfcheck.h new file mode 100644 index 00000000..92bb5113 --- /dev/null +++ b/mbfido/mbfcheck.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFCHECK_H_ +#define _MBFCHECK_H + +void Check(void); /* Check file database */ + +#endif diff --git a/mbfido/mbfile.c b/mbfido/mbfile.c index d99a1f11..17054fce 100644 --- a/mbfido/mbfile.c +++ b/mbfido/mbfile.c @@ -34,11 +34,19 @@ #include "../lib/common.h" #include "../lib/clcomm.h" #include "../lib/dbcfg.h" +#include "mbfkill.h" +#include "mbfadopt.h" +#include "mbfindex.h" +#include "mbfcheck.h" +#include "mbfpack.h" +#include "mbflist.h" +#include "mbfutil.h" #include "mbfile.h" extern int do_quiet; /* Supress screen output */ +int do_adopt = FALSE; /* Adopt a file */ int do_pack = FALSE; /* Pack filebase */ int do_check = FALSE; /* Check filebase */ int do_kill = FALSE; /* Kill/move old files */ @@ -48,75 +56,13 @@ extern int e_pid; /* Pid of external process */ extern int show_log; /* Show logging */ time_t t_start; /* Start time */ time_t t_end; /* End time */ -int marker = 0; /* Marker counter */ - - -typedef struct _Index { - struct _Index *next; - struct FILEIndex idx; -} Findex; - - -void ProgName(void) -{ - if (do_quiet) - return; - - colour(15, 0); - printf("\nMBFILE: MBSE BBS %s File maintenance utility\n", VERSION); - colour(14, 0); - printf(" %s\n", COPYRIGHT); -} - - - -void die(int onsig) -{ - /* - * First check if a child is running, if so, kill it. - */ - if (e_pid) { - if ((kill(e_pid, SIGTERM)) == 0) - Syslog('+', "SIGTERM to pid %d succeeded", e_pid); - else { - if ((kill(e_pid, SIGKILL)) == 0) - Syslog('+', "SIGKILL to pid %d succeded", e_pid); - else - WriteError("$Failed to kill pid %d", e_pid); - } - - /* - * In case the child had the tty in raw mode... - */ - if (!do_quiet) - system("stty sane"); - } - - signal(onsig, SIG_IGN); - - if (onsig) { - if (onsig <= NSIG) - WriteError("$Terminated on signal %d (%s)", onsig, SigName[onsig]); - else - WriteError("Terminated with error %d", onsig); - } - - time(&t_end); - Syslog(' ', "MBFILE finished in %s", t_elapsed(t_start, t_end)); - - if (!do_quiet) { - colour(7, 0); - printf("\n"); - } - ExitClient(onsig); -} int main(int argc, char **argv) { - int i; - char *cmd; + int i, Area = 0; + char *cmd, *FileName = NULL, *Description = NULL; struct passwd *pw; #ifdef MEMWATCH @@ -148,6 +94,23 @@ int main(int argc, char **argv) cmd = xstrcat(cmd, (char *)" "); cmd = xstrcat(cmd, tl(argv[i])); + if (!strncmp(argv[i], "a", 1)) { + do_adopt = TRUE; + i++; + Area = atoi(argv[i]); + cmd = xstrcat(cmd, (char *)" "); + cmd = xstrcat(cmd, argv[i]); + i++; + FileName = xstrcpy(argv[i]); + cmd = xstrcat(cmd, (char *)" "); + cmd = xstrcat(cmd, argv[i]); + if (argc > (i + 1)) { + i++; + Description = xstrcpy(argv[i]); + cmd = xstrcat(cmd, (char *)" "); + cmd = xstrcat(cmd, argv[i]); + } + } if (!strncmp(argv[i], "in", 2)) do_index = TRUE; if (!strncmp(argv[i], "l", 1)) @@ -162,7 +125,7 @@ int main(int argc, char **argv) do_quiet = TRUE; } - if (!(do_pack || do_check || do_kill || do_index || do_list)) + if (!(do_pack || do_check || do_kill || do_index || do_list || do_adopt)) Help(); ProgName(); @@ -180,6 +143,9 @@ int main(int argc, char **argv) if (!diskfree(CFG.freespace)) die(101); + if (do_adopt) + AdoptFile(Area, FileName, Description); + if (do_kill) Kill(); @@ -201,896 +167,4 @@ int main(int argc, char **argv) -void Help(void) -{ - do_quiet = FALSE; - ProgName(); - - colour(11, 0); - printf("\nUsage: mbfile [command] \n\n"); - colour(9, 0); - printf(" Commands are:\n\n"); - colour(3, 0); -// printf(" a adopt [desc] Adopt file to area\n"); - printf(" c check Check filebase\n"); -// printf(" d delete Mark file in area for deletion\n"); -// printf(" im import Import files in current dir to area\n"); - printf(" in index Create filerequest index\n"); - printf(" k kill Kill/move old files\n"); - printf(" l list List file areas\n"); -// printf(" m move Move file from to area\n"); - printf(" p pack Pack filebase\n"); -// printf(" r rearc [file] [arc] Rearc file(s) in area\n"); - colour(9, 0); - printf("\n Options are:\n\n"); - colour(3, 0); - printf(" -q -quiet Quiet mode\n"); - colour(7, 0); - printf("\n"); - die(0); -} - - - -void Marker(void) -{ - /* - * Keep the connection with the server alive - */ - Nopper(); - - /* - * Release system resources when running in the background - */ - if (CFG.slow_util && do_quiet) - usleep(1); - - if (do_quiet) - return; - - switch (marker) { - case 0: printf(">---"); - break; - - case 1: printf(">>--"); - break; - - case 2: printf(">>>-"); - break; - - case 3: printf(">>>>"); - break; - - case 4: printf("<>>>"); - break; - - case 5: printf("<<>>"); - break; - - case 6: printf("<<<>"); - break; - - case 7: printf("<<<<"); - break; - - case 8: printf("-<<<"); - break; - - case 9: printf("--<<"); - break; - - case 10:printf("---<"); - break; - - case 11:printf("----"); - break; - } - printf("\b\b\b\b"); - fflush(stdout); - - if (marker < 11) - marker++; - else - marker = 0; -} - - - -/* - * Check files for age, and not downloaded for x days. If they match - * one of these criteria (setable in areas setup), the file will be - * move to some retire area or deleted, depending on the setup. - * If they are moved, the upload date is reset to the current date, - * so you can set new removal criteria again. - */ -void Kill(void) -{ - FILE *pAreas, *pFile, *pDest, *pTemp; - int i, iAreas, iAreasNew = 0; - int iTotal = 0, iKilled = 0, iMoved = 0; - char *sAreas, *fAreas, *newdir = NULL, *sTemp; - time_t Now; - int rc, Killit, FilesLeft; - struct fileareas darea; - char from[PATH_MAX], to[PATH_MAX]; - - sAreas = calloc(PATH_MAX, sizeof(char)); - fAreas = calloc(PATH_MAX, sizeof(char)); - sTemp = calloc(PATH_MAX, sizeof(char)); - - IsDoing("Kill files"); - if (!do_quiet) { - colour(3, 0); - printf("Kill/move files...\n"); - } - - sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); - - if ((pAreas = fopen (sAreas, "r")) == NULL) { - WriteError("Can't open %s", sAreas); - die(0); - } - - fread(&areahdr, sizeof(areahdr), 1, pAreas); - fseek(pAreas, 0, SEEK_END); - iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; - Now = time(NULL); - - for (i = 1; i <= iAreas; i++) { - - fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&area, areahdr.recsize, 1, pAreas); - - if ((area.Available) && (area.DLdays || area.FDdays) && (!area.CDrom)) { - - if (!diskfree(CFG.freespace)) - die(101); - - if (!do_quiet) { - printf("\r%4d => %-44s \b\b\b\b", i, area.Name); - fflush(stdout); - } - - /* - * Check if download directory exists, - * if not, create the directory. - */ - if (access(area.Path, R_OK) == -1) { - Syslog('!', "Create dir: %s", area.Path); - newdir = xstrcpy(area.Path); - newdir = xstrcat(newdir, (char *)"/"); - mkdirs(newdir); - free(newdir); - newdir = NULL; - } - - sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); - - /* - * Open the file database, if it doesn't exist, - * create an empty one. - */ - if ((pFile = fopen(fAreas, "r+")) == NULL) { - Syslog('!', "Creating new %s", fAreas); - if ((pFile = fopen(fAreas, "a+")) == NULL) { - WriteError("$Can't create %s", fAreas); - die(0); - } - } - - /* - * Now start checking the files in the filedatabase - * against the contents of the directory. - */ - while (fread(&file, sizeof(file), 1, pFile) == 1) { - iTotal++; - Marker(); - - Killit = FALSE; - if (area.DLdays) { - /* - * Test last download date or never downloaded and the - * file is more then n days available for download. - */ - if ((file.LastDL) && - (((Now - file.LastDL) / 84400) > area.DLdays)) { - Killit = TRUE; - } - if ((!file.LastDL) && - (((Now - file.UploadDate) / 84400) > area.DLdays)) { - Killit = TRUE; - } - } - - if (area.FDdays) { - /* - * Check filedate - */ - if (((Now - file.UploadDate) / 84400) > area.FDdays) { - Killit = TRUE; - } - } - - if (Killit) { - do_pack = TRUE; - if (area.MoveArea) { - fseek(pAreas, ((area.MoveArea -1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&darea, areahdr.recsize, 1, pAreas); - sprintf(from, "%s/%s", area.Path, file.Name); - sprintf(to, "%s/%s", darea.Path, file.Name); - if ((rc = file_mv(from, to)) == 0) { - Syslog('+', "Move %s, area %d => %d", file.Name, i, area.MoveArea); - sprintf(to, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), area.MoveArea); - if ((pDest = fopen(to, "a+")) != NULL) { - file.UploadDate = time(NULL); - file.LastDL = time(NULL); - fwrite(&file, sizeof(file), 1, pDest); - fclose(pDest); - } - /* - * Now again if there is a dotted version (thumbnail) of this file. - */ - sprintf(from, "%s/.%s", area.Path, file.Name); - sprintf(to, "%s/.%s", darea.Path, file.Name); - if (file_exist(from, R_OK) == 0) - file_mv(from, to); - file.Deleted = TRUE; - fseek(pFile, - sizeof(file), SEEK_CUR); - fwrite(&file, sizeof(file), 1, pFile); - iMoved++; - } else { - WriteError("Move %s failed rc = %d", file.Name, rc); - } - } else { - Syslog('+', "Delete %s, area %d", file.Name, i); - file.Deleted = TRUE; - fseek(pFile, - sizeof(file), SEEK_CUR); - fwrite(&file, sizeof(file), 1, pFile); - iKilled++; - sprintf(from, "%s/%s", area.Path, file.Name); - unlink(from); - } - } - } - - /* - * Now we must pack this area database otherwise - * we run into trouble later on. - */ - fseek(pFile, 0, SEEK_SET); - sprintf(sTemp, "%s/fdb/fdbtmp.data", getenv("MBSE_ROOT")); - - if ((pTemp = fopen(sTemp, "a+")) != NULL) { - FilesLeft = FALSE; - while (fread(&file, sizeof(file), 1, pFile) == 1) { - if ((!file.Deleted) && strcmp(file.Name, "") != 0) { - fwrite(&file, sizeof(file), 1, pTemp); - FilesLeft = TRUE; - } - } - - fclose(pFile); - fclose(pTemp); - if ((rename(sTemp, fAreas)) == 0) { - unlink(sTemp); - chmod(fAreas, 006600); - } - if (!FilesLeft) { - Syslog('+', "Warning: area %d (%s) is empty", i, area.Name); - } - } else - fclose(pFile); - - iAreasNew++; - - } /* if area.Available */ - } - - fclose(pAreas); - - Syslog('+', "Kill Areas [%5d] Files [%5d] Deleted [%5d] Moved [%5d]", iAreasNew, iTotal, iKilled, iMoved); - - if (!do_quiet) { - printf("\r \r"); - fflush(stdout); - } - - free(sTemp); - free(sAreas); - free(fAreas); -} - - - -void tidy_index(Findex **); -void tidy_index(Findex **fap) -{ - Findex *tmp, *old; - - for (tmp = *fap; tmp; tmp = old) { - old = tmp->next; - free(tmp); - } - *fap = NULL; -} - - - -void fill_index(struct FILEIndex, Findex **); -void fill_index(struct FILEIndex idx, Findex **fap) -{ - Findex *tmp; - - tmp = (Findex *)malloc(sizeof(Findex)); - tmp->next = *fap; - tmp->idx = idx; - *fap = tmp; -} - - -int comp_index(Findex **, Findex **); - -void sort_index(Findex **); -void sort_index(Findex **fap) -{ - Findex *ta, **vector; - size_t n = 0, i; - - if (*fap == NULL) - return; - - for (ta = *fap; ta; ta = ta->next) - n++; - - vector = (Findex **)malloc(n * sizeof(Findex *)); - - i = 0; - for (ta = *fap; ta; ta = ta->next) - vector[i++] = ta; - - qsort(vector, n, sizeof(Findex *), - (int(*)(const void*, const void *))comp_index); - - (*fap) = vector[0]; - i = 1; - - for (ta = *fap; ta; ta = ta->next) { - if (i < n) - ta->next = vector[i++]; - else - ta->next = NULL; - } - - free(vector); - return; -} - - - -int comp_index(Findex **fap1, Findex **fap2) -{ - return strcasecmp((*fap1)->idx.LName, (*fap2)->idx.LName); -} - - - -/* - * Build a sorted index for the file request processor. - */ -void Index(void) -{ - FILE *pAreas, *pFile, *pIndex; - long i, iAreas, iAreasNew = 0, record; - int iTotal = 0; - char *sAreas, *fAreas, *newdir = NULL, *sIndex; - Findex *fdx = NULL; - Findex *tmp; - struct FILEIndex idx; - - sAreas = calloc(PATH_MAX, sizeof(char)); - fAreas = calloc(PATH_MAX, sizeof(char)); - sIndex = calloc(PATH_MAX, sizeof(char)); - - IsDoing("Kill files"); - if (!do_quiet) { - colour(3, 0); - printf("Create filerequest index...\n"); - } - - sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); - - if ((pAreas = fopen (sAreas, "r")) == NULL) { - WriteError("$Can't open %s", sAreas); - die(0); - } - - sprintf(sIndex, "%s/etc/request.index", getenv("MBSE_ROOT")); - if ((pIndex = fopen(sIndex, "w")) == NULL) { - WriteError("$Can't create %s", sIndex); - die(0); - } - - fread(&areahdr, sizeof(areahdr), 1, pAreas); - fseek(pAreas, 0, SEEK_END); - iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; - - for (i = 1; i <= iAreas; i++) { - - fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&area, areahdr.recsize, 1, pAreas); - - if ((area.Available) && (area.FileReq)) { - - if (!diskfree(CFG.freespace)) - die(101); - - if (!do_quiet) { - printf("\r%4ld => %-44s \b\b\b\b", i, area.Name); - fflush(stdout); - } - - /* - * Check if download directory exists, - * if not, create the directory. - */ - if (access(area.Path, R_OK) == -1) { - Syslog('!', "Create dir: %s", area.Path); - newdir = xstrcpy(area.Path); - newdir = xstrcat(newdir, (char *)"/"); - mkdirs(newdir); - free(newdir); - newdir = NULL; - } - - sprintf(fAreas, "%s/fdb/fdb%ld.data", getenv("MBSE_ROOT"), i); - - /* - * Open the file database, if it doesn't exist, - * create an empty one. - */ - if ((pFile = fopen(fAreas, "r+")) == NULL) { - Syslog('!', "Creating new %s", fAreas); - if ((pFile = fopen(fAreas, "a+")) == NULL) { - WriteError("$Can't create %s", fAreas); - die(0); - } - } - - /* - * Now start creating the unsorted index. - */ - record = 0; - while (fread(&file, sizeof(file), 1, pFile) == 1) { - iTotal++; - if ((iTotal % 10) == 0) - Marker(); - memset(&idx, 0, sizeof(idx)); - sprintf(idx.Name, "%s", tu(file.Name)); - sprintf(idx.LName, "%s", tu(file.LName)); - idx.AreaNum = i; - idx.Record = record; - fill_index(idx, &fdx); - record++; - } - - fclose(pFile); - iAreasNew++; - - } /* if area.Available */ - } - - fclose(pAreas); - - sort_index(&fdx); - for (tmp = fdx; tmp; tmp = tmp->next) - fwrite(&tmp->idx, sizeof(struct FILEIndex), 1, pIndex); - fclose(pIndex); - tidy_index(&fdx); - - Syslog('+', "Index Areas [%5d] Files [%5d]", iAreasNew, iTotal); - - if (!do_quiet) { - printf("\r \r"); - fflush(stdout); - } - - free(sIndex); - free(sAreas); - free(fAreas); - RemoveSema((char *)"reqindex"); -} - - - -/* - * Check file database integrity, all files in the file database must - * exist in real, the size and date/time must match, the files crc is - * checked, and if anything is wrong, the file database is updated. - * If the file is missing the entry is marked as deleted. With the - * pack option that record will be removed. - * After these checks, de database is checked for missing records, if - * there are files on disk but not in the directory these files are - * deleted. System files (beginning with a dot) are left alone and - * the files 'files.bbs', 'files.bak', '00index', 'header' 'readme' - * and 'index.html' too. - * - * Remarks: Maybe if the crc check fails, and the date and time are - * ok, the file is damaged and must be made unavailable. - */ -void Check(void) -{ - FILE *pAreas, *pFile; - int i, iAreas, iAreasNew = 0; - int iTotal = 0, iErrors = 0; - char *sAreas, *fAreas, *newdir; - DIR *dp; - struct dirent *de; - int Found, Update; - char fn[PATH_MAX]; - struct stat stb; - - sAreas = calloc(PATH_MAX, sizeof(char)); - fAreas = calloc(PATH_MAX, sizeof(char)); - newdir = calloc(PATH_MAX, sizeof(char)); - - if (!do_quiet) { - colour(3, 0); - printf("Checking file database...\n"); - } - - sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); - - if ((pAreas = fopen (sAreas, "r")) == NULL) { - WriteError("Can't open %s", sAreas); - die(0); - } - - fread(&areahdr, sizeof(areahdr), 1, pAreas); - fseek(pAreas, 0, SEEK_END); - iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; - - for (i = 1; i <= iAreas; i++) { - - fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&area, areahdr.recsize, 1, pAreas); - - if (area.Available) { - - IsDoing("Check area %d", i); - - if (!do_quiet) { - printf("\r%4d => %-44s \b\b\b\b", i, area.Name); - fflush(stdout); - } - - /* - * Check if download directory exists, - * if not, create the directory. - */ - if (access(area.Path, R_OK) == -1) { - Syslog('!', "No dir: %s", area.Path); - sprintf(newdir, "%s/foobar", area.Path); - mkdirs(newdir); - } - - sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); - - /* - * Open the file database, if it doesn't exist, - * create an empty one. - */ - if ((pFile = fopen(fAreas, "r+")) == NULL) { - Syslog('!', "Creating new %s", fAreas); - if ((pFile = fopen(fAreas, "a+")) == NULL) { - WriteError("$Can't create %s", fAreas); - die(0); - } - } - - /* - * Now start checking the files in the filedatabase - * against the contents of the directory. - */ - while (fread(&file, sizeof(file), 1, pFile) == 1) { - - iTotal++; - sprintf(newdir, "%s/%s", area.Path, file.Name); - - if (file_exist(newdir, R_OK)) { - Syslog('+', "File %s area %d not on disk.", newdir, i); - if (!file.NoKill) { - file.Deleted = TRUE; - do_pack = TRUE; - } - iErrors++; - file.Missing = TRUE; - fseek(pFile, - sizeof(file), SEEK_CUR); - fwrite(&file, sizeof(file), 1, pFile); - } else { - /* - * File exists, now check the file. - */ - Marker(); - Update = FALSE; - if (file_time(newdir) != file.FileDate) { - Syslog('!', "Date mismatch area %d file %s", i, file.Name); - file.FileDate = file_time(newdir); - iErrors++; - Update = TRUE; - } - if (file_size(newdir) != file.Size) { - Syslog('!', "Size mismatch area %d file %s", i, file.Name); - file.Size = file_size(newdir); - iErrors++; - Update = TRUE; - } - if (file_crc(newdir, CFG.slow_util && do_quiet) != file.Crc32) { - Syslog('!', "CRC error area %d, file %s", i, file.Name); - file.Crc32 = file_crc(newdir, CFG.slow_util && do_quiet); - iErrors++; - Update = TRUE; - } - Marker(); - if (Update) { - fseek(pFile, - sizeof(file), SEEK_CUR); - fwrite(&file, sizeof(file), 1, pFile); - } - } - } - - /* - * Check files in the directory against the database. - * This test is skipped for CD-rom. - */ - if (!area.CDrom) { - if ((dp = opendir(area.Path)) != NULL) { - while ((de = readdir(dp)) != NULL) { - if (de->d_name[0] != '.') { - Marker(); - Found = FALSE; - rewind(pFile); - while (fread(&file, sizeof(file), 1, pFile) == 1) { - if (strcmp(file.Name, de->d_name) == 0) { - Found = TRUE; - break; - } - } - if ((!Found) && - (strncmp(de->d_name, "files.bbs", 9)) && - (strncmp(de->d_name, "files.bak", 9)) && - (strncmp(de->d_name, "00index", 7)) && - (strncmp(de->d_name, "header", 6)) && - (strncmp(de->d_name, "index", 5)) && - (strncmp(de->d_name, "readme", 6))) { - sprintf(fn, "%s/%s", area.Path, de->d_name); - if (stat(fn, &stb) == 0) - if (S_ISREG(stb.st_mode)) { - if (unlink(fn) == 0) { - Syslog('!', "%s not in fdb, deleted from disk", fn); - iErrors++; - } else { - WriteError("$%s not in fdb, cannot delete", fn); - } - } - } - } - } - closedir(dp); - } else { - WriteError("Can't open %s", area.Path); - } - } - - fclose(pFile); - iAreasNew++; - - } /* if area.Available */ - } - - fclose(pAreas); - if (!do_quiet) { - printf("\r \r"); - fflush(stdout); - } - - free(newdir); - free(sAreas); - free(fAreas); - - Syslog('+', "Check Areas [%5d] Files [%5d] Errors [%5d]", iAreasNew, iTotal, iErrors); -} - - - -/* - * Removes records who are marked for deletion. If there is still a file - * on disk, it will be removed too. - */ -void PackFileBase(void) -{ - FILE *fp, *pAreas, *pFile; - int i, iAreas, iAreasNew = 0; - int iTotal = 0, iRemoved = 0; - char *sAreas, *fAreas, *fTmp, fn[PATH_MAX]; - - sAreas = calloc(PATH_MAX, sizeof(char)); - fAreas = calloc(PATH_MAX, sizeof(char)); - fTmp = calloc(PATH_MAX, sizeof(char)); - - IsDoing("Pack filebase"); - if (!do_quiet) { - colour(3, 0); - printf("Packing file database...\n"); - } - - sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); - - if ((pAreas = fopen (sAreas, "r")) == NULL) { - WriteError("Can't open %s", sAreas); - die(0); - } - - fread(&areahdr, sizeof(areahdr), 1, pAreas); - fseek(pAreas, 0, SEEK_END); - iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; - - for (i = 1; i <= iAreas; i++) { - - fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&area, areahdr.recsize, 1, pAreas); - - if (area.Available && !area.CDrom) { - - if (!diskfree(CFG.freespace)) - die(101); - - if (!do_quiet) { - printf("\r%4d => %-44s", i, area.Name); - fflush(stdout); - } - Marker(); - - sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); - sprintf(fTmp, "%s/fdb/fdbtmp.data", getenv("MBSE_ROOT")); - - if ((pFile = fopen(fAreas, "r")) == NULL) { - Syslog('!', "Creating new %s", fAreas); - if ((pFile = fopen(fAreas, "a+")) == NULL) { - WriteError("$Can't create %s", fAreas); - die(0); - } - } - - if ((fp = fopen(fTmp, "a+")) == NULL) { - WriteError("$Can't create %s", fTmp); - die(0); - } - - while (fread(&file, sizeof(file), 1, pFile) == 1) { - - iTotal++; - - if ((!file.Deleted) && (strcmp(file.Name, "") != 0)) { - fwrite(&file, sizeof(file), 1, fp); - } else { - iRemoved++; - Syslog('+', "Removed file \"%s\" from area %d", file.Name, i); - sprintf(fn, "%s/%s", area.Path, file.Name); - Syslog('+', "Unlink %s result %d", fn, unlink(fn)); - /* - * If a dotted version (thumbnail) exists, remove it silently - */ - sprintf(fn, "%s/.%s", area.Path, file.Name); - unlink(fn); - } - } - - fclose(fp); - fclose(pFile); - - if ((rename(fTmp, fAreas)) == 0) { - unlink(fTmp); - chmod(fAreas, 00660); - } - iAreasNew++; - - } /* if area.Available */ - } - - fclose(pAreas); - Syslog('+', "Pack Areas [%5d] Files [%5d] Removed [%5d]", iAreasNew, iTotal, iRemoved); - - if (!do_quiet) { - printf("\r \r"); - fflush(stdout); - } - - free(fTmp); - free(sAreas); - free(fAreas); -} - - -void ListFileAreas(void) -{ - FILE *pAreas, *pFile; - int i, iAreas, fcount, tcount = 0; - int iTotal = 0; - long fsize, tsize = 0; - char *sAreas, *fAreas; - - sAreas = calloc(PATH_MAX, sizeof(char)); - fAreas = calloc(PATH_MAX, sizeof(char)); - - IsDoing("List fileareas"); - if (!do_quiet) { - colour(3, 0); - printf(" Area Files MByte File Group Area name\n"); - printf("----- ----- ----- ------------ --------------------------------------------\n"); - colour(7, 0); - } - - sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); - - if ((pAreas = fopen (sAreas, "r")) == NULL) { - WriteError("Can't open %s", sAreas); - if (!do_quiet) - printf("Can't open %s\n", sAreas); - die(0); - } - - fread(&areahdr, sizeof(areahdr), 1, pAreas); - fseek(pAreas, 0, SEEK_END); - iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; - - for (i = 1; i <= iAreas; i++) { - fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); - fread(&area, areahdr.recsize, 1, pAreas); - - if (area.Available) { - - sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); - - /* - * Open the file database, create new one if it doesn't excist. - */ - if ((pFile = fopen(fAreas, "r+")) == NULL) { - Syslog('!', "Creating new %s", fAreas); - if ((pFile = fopen(fAreas, "a+")) == NULL) { - WriteError("$Can't create %s", fAreas); - die(0); - } - } - - fcount = 0; - fsize = 0L; - while (fread(&file, sizeof(file), 1, pFile) == 1) { - fcount++; - fsize = fsize + file.Size; - } - fsize = fsize / 1048576; - tcount += fcount; - tsize += fsize; - - if (!do_quiet) - printf("%5d %5d %5ld %-12s %s\n", i, fcount, fsize, area.BbsGroup, area.Name); - iTotal++; - } - } - - if (!do_quiet) { - colour(3, 0); - printf("----- ----- ----- ---------------------------------------------------------\n"); - printf("%5d %5d %5ld \n", iTotal, tcount, tsize); - } - - fclose(pAreas); - if (!do_quiet) { - printf("\r \r"); - fflush(stdout); - } - - free(sAreas); - free(fAreas); -} diff --git a/mbfido/mbfile.h b/mbfido/mbfile.h index b8ed74b3..2e9cb1d6 100644 --- a/mbfido/mbfile.h +++ b/mbfido/mbfile.h @@ -1,14 +1,7 @@ +/* $Id$ */ + #ifndef _MBFILE_H_ #define _MBFILE_H -void Help(void); /* Show help screen */ -void Check(void); /* Check file database */ -void Index(void); /* Index filerquest */ -void Req(void); /* Check symlinks */ -void Kill(void); /* Kill/move old files */ -void PackFileBase(void); /* Pack / Compress File Base */ -void CreateWeb(void); /* Create WWW pages */ -void ListFileAreas(void); /* List fileareas */ #endif - diff --git a/mbfido/mbfindex.c b/mbfido/mbfindex.c new file mode 100644 index 00000000..9f21c594 --- /dev/null +++ b/mbfido/mbfindex.c @@ -0,0 +1,251 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - Build index for request processor + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbfindex.h" + + + +extern int do_quiet; /* Supress screen output */ + + +typedef struct _Index { + struct _Index *next; + struct FILEIndex idx; +} Findex; + + + +void tidy_index(Findex **); +void tidy_index(Findex **fap) +{ + Findex *tmp, *old; + + for (tmp = *fap; tmp; tmp = old) { + old = tmp->next; + free(tmp); + } + *fap = NULL; +} + + + +void fill_index(struct FILEIndex, Findex **); +void fill_index(struct FILEIndex idx, Findex **fap) +{ + Findex *tmp; + + tmp = (Findex *)malloc(sizeof(Findex)); + tmp->next = *fap; + tmp->idx = idx; + *fap = tmp; +} + + +int comp_index(Findex **, Findex **); + +void sort_index(Findex **); +void sort_index(Findex **fap) +{ + Findex *ta, **vector; + size_t n = 0, i; + + if (*fap == NULL) + return; + + for (ta = *fap; ta; ta = ta->next) + n++; + + vector = (Findex **)malloc(n * sizeof(Findex *)); + + i = 0; + for (ta = *fap; ta; ta = ta->next) + vector[i++] = ta; + + qsort(vector, n, sizeof(Findex *), + (int(*)(const void*, const void *))comp_index); + + (*fap) = vector[0]; + i = 1; + + for (ta = *fap; ta; ta = ta->next) { + if (i < n) + ta->next = vector[i++]; + else + ta->next = NULL; + } + + free(vector); + return; +} + + + +int comp_index(Findex **fap1, Findex **fap2) +{ + return strcasecmp((*fap1)->idx.LName, (*fap2)->idx.LName); +} + + + +/* + * Build a sorted index for the file request processor. + */ +void Index(void) +{ + FILE *pAreas, *pFile, *pIndex; + long i, iAreas, iAreasNew = 0, record; + int iTotal = 0; + char *sAreas, *fAreas, *newdir = NULL, *sIndex; + Findex *fdx = NULL; + Findex *tmp; + struct FILEIndex idx; + + sAreas = calloc(PATH_MAX, sizeof(char)); + fAreas = calloc(PATH_MAX, sizeof(char)); + sIndex = calloc(PATH_MAX, sizeof(char)); + + IsDoing("Kill files"); + if (!do_quiet) { + colour(3, 0); + printf("Create filerequest index...\n"); + } + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("$Can't open %s", sAreas); + die(0); + } + + sprintf(sIndex, "%s/etc/request.index", getenv("MBSE_ROOT")); + if ((pIndex = fopen(sIndex, "w")) == NULL) { + WriteError("$Can't create %s", sIndex); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + fseek(pAreas, 0, SEEK_END); + iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; + + for (i = 1; i <= iAreas; i++) { + + fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&area, areahdr.recsize, 1, pAreas); + + if ((area.Available) && (area.FileReq)) { + + if (!diskfree(CFG.freespace)) + die(101); + + if (!do_quiet) { + printf("\r%4ld => %-44s \b\b\b\b", i, area.Name); + fflush(stdout); + } + + /* + * Check if download directory exists, + * if not, create the directory. + */ + if (access(area.Path, R_OK) == -1) { + Syslog('!', "Create dir: %s", area.Path); + newdir = xstrcpy(area.Path); + newdir = xstrcat(newdir, (char *)"/"); + mkdirs(newdir); + free(newdir); + newdir = NULL; + } + + sprintf(fAreas, "%s/fdb/fdb%ld.data", getenv("MBSE_ROOT"), i); + + /* + * Open the file database, if it doesn't exist, + * create an empty one. + */ + if ((pFile = fopen(fAreas, "r+")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + /* + * Now start creating the unsorted index. + */ + record = 0; + while (fread(&file, sizeof(file), 1, pFile) == 1) { + iTotal++; + if ((iTotal % 10) == 0) + Marker(); + memset(&idx, 0, sizeof(idx)); + sprintf(idx.Name, "%s", tu(file.Name)); + sprintf(idx.LName, "%s", tu(file.LName)); + idx.AreaNum = i; + idx.Record = record; + fill_index(idx, &fdx); + record++; + } + + fclose(pFile); + iAreasNew++; + + } /* if area.Available */ + } + + fclose(pAreas); + + sort_index(&fdx); + for (tmp = fdx; tmp; tmp = tmp->next) + fwrite(&tmp->idx, sizeof(struct FILEIndex), 1, pIndex); + fclose(pIndex); + tidy_index(&fdx); + + Syslog('+', "Index Areas [%5d] Files [%5d]", iAreasNew, iTotal); + + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(sIndex); + free(sAreas); + free(fAreas); + RemoveSema((char *)"reqindex"); +} + + + diff --git a/mbfido/mbfindex.h b/mbfido/mbfindex.h new file mode 100644 index 00000000..e853fdba --- /dev/null +++ b/mbfido/mbfindex.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFINDEX_H_ +#define _MBFINDEX_H + +void Index(void); /* Index filerquest */ + +#endif diff --git a/mbfido/mbfkill.c b/mbfido/mbfkill.c new file mode 100644 index 00000000..cda4db51 --- /dev/null +++ b/mbfido/mbfkill.c @@ -0,0 +1,252 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance, kill or move old files + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfkill.h" +#include "mbfutil.h" + + + +extern int do_quiet; /* Supress screen output */ +extern int do_pack; /* Perform pack */ + + + +/* + * Check files for age, and not downloaded for x days. If they match + * one of these criteria (setable in areas setup), the file will be + * move to some retire area or deleted, depending on the setup. + * If they are moved, the upload date is reset to the current date, + * so you can set new removal criteria again. + */ +void Kill(void) +{ + FILE *pAreas, *pFile, *pDest, *pTemp; + int i, iAreas, iAreasNew = 0; + int iTotal = 0, iKilled = 0, iMoved = 0; + char *sAreas, *fAreas, *newdir = NULL, *sTemp; + time_t Now; + int rc, Killit, FilesLeft; + struct fileareas darea; + char from[PATH_MAX], to[PATH_MAX]; + + sAreas = calloc(PATH_MAX, sizeof(char)); + fAreas = calloc(PATH_MAX, sizeof(char)); + sTemp = calloc(PATH_MAX, sizeof(char)); + + IsDoing("Kill files"); + if (!do_quiet) { + colour(3, 0); + printf("Kill/move files...\n"); + } + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("Can't open %s", sAreas); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + fseek(pAreas, 0, SEEK_END); + iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; + Now = time(NULL); + + for (i = 1; i <= iAreas; i++) { + + fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&area, areahdr.recsize, 1, pAreas); + + if ((area.Available) && (area.DLdays || area.FDdays) && (!area.CDrom)) { + + if (!diskfree(CFG.freespace)) + die(101); + + if (!do_quiet) { + printf("\r%4d => %-44s \b\b\b\b", i, area.Name); + fflush(stdout); + } + + /* + * Check if download directory exists, + * if not, create the directory. + */ + if (access(area.Path, R_OK) == -1) { + Syslog('!', "Create dir: %s", area.Path); + newdir = xstrcpy(area.Path); + newdir = xstrcat(newdir, (char *)"/"); + mkdirs(newdir); + free(newdir); + newdir = NULL; + } + + sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); + + /* + * Open the file database, if it doesn't exist, + * create an empty one. + */ + if ((pFile = fopen(fAreas, "r+")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + /* + * Now start checking the files in the filedatabase + * against the contents of the directory. + */ + while (fread(&file, sizeof(file), 1, pFile) == 1) { + iTotal++; + Marker(); + + Killit = FALSE; + if (area.DLdays) { + /* + * Test last download date or never downloaded and the + * file is more then n days available for download. + */ + if ((file.LastDL) && + (((Now - file.LastDL) / 84400) > area.DLdays)) { + Killit = TRUE; + } + if ((!file.LastDL) && + (((Now - file.UploadDate) / 84400) > area.DLdays)) { + Killit = TRUE; + } + } + + if (area.FDdays) { + /* + * Check filedate + */ + if (((Now - file.UploadDate) / 84400) > area.FDdays) { + Killit = TRUE; + } + } + + if (Killit) { + do_pack = TRUE; + if (area.MoveArea) { + fseek(pAreas, ((area.MoveArea -1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&darea, areahdr.recsize, 1, pAreas); + sprintf(from, "%s/%s", area.Path, file.Name); + sprintf(to, "%s/%s", darea.Path, file.Name); + if ((rc = file_mv(from, to)) == 0) { + Syslog('+', "Move %s, area %d => %d", file.Name, i, area.MoveArea); + sprintf(to, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), area.MoveArea); + if ((pDest = fopen(to, "a+")) != NULL) { + file.UploadDate = time(NULL); + file.LastDL = time(NULL); + fwrite(&file, sizeof(file), 1, pDest); + fclose(pDest); + } + /* + * Now again if there is a dotted version (thumbnail) of this file. + */ + sprintf(from, "%s/.%s", area.Path, file.Name); + sprintf(to, "%s/.%s", darea.Path, file.Name); + if (file_exist(from, R_OK) == 0) + file_mv(from, to); + file.Deleted = TRUE; + fseek(pFile, - sizeof(file), SEEK_CUR); + fwrite(&file, sizeof(file), 1, pFile); + iMoved++; + } else { + WriteError("Move %s failed rc = %d", file.Name, rc); + } + } else { + Syslog('+', "Delete %s, area %d", file.Name, i); + file.Deleted = TRUE; + fseek(pFile, - sizeof(file), SEEK_CUR); + fwrite(&file, sizeof(file), 1, pFile); + iKilled++; + sprintf(from, "%s/%s", area.Path, file.Name); + unlink(from); + } + } + } + + /* + * Now we must pack this area database otherwise + * we run into trouble later on. + */ + fseek(pFile, 0, SEEK_SET); + sprintf(sTemp, "%s/fdb/fdbtmp.data", getenv("MBSE_ROOT")); + + if ((pTemp = fopen(sTemp, "a+")) != NULL) { + FilesLeft = FALSE; + while (fread(&file, sizeof(file), 1, pFile) == 1) { + if ((!file.Deleted) && strcmp(file.Name, "") != 0) { + fwrite(&file, sizeof(file), 1, pTemp); + FilesLeft = TRUE; + } + } + + fclose(pFile); + fclose(pTemp); + if ((rename(sTemp, fAreas)) == 0) { + unlink(sTemp); + chmod(fAreas, 006600); + } + if (!FilesLeft) { + Syslog('+', "Warning: area %d (%s) is empty", i, area.Name); + } + } else + fclose(pFile); + + iAreasNew++; + + } /* if area.Available */ + } + + fclose(pAreas); + + Syslog('+', "Kill Areas [%5d] Files [%5d] Deleted [%5d] Moved [%5d]", iAreasNew, iTotal, iKilled, iMoved); + + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(sTemp); + free(sAreas); + free(fAreas); +} + + + diff --git a/mbfido/mbfkill.h b/mbfido/mbfkill.h new file mode 100644 index 00000000..bea122c7 --- /dev/null +++ b/mbfido/mbfkill.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFKILL_H +#define _MBFKILL_H + +void Kill(void); + +#endif diff --git a/mbfido/mbflist.c b/mbfido/mbflist.c new file mode 100644 index 00000000..44056c28 --- /dev/null +++ b/mbfido/mbflist.c @@ -0,0 +1,127 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - List areas and totals + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbflist.h" + + + +extern int do_quiet; /* Supress screen output */ + + +void ListFileAreas(void) +{ + FILE *pAreas, *pFile; + int i, iAreas, fcount, tcount = 0; + int iTotal = 0; + long fsize, tsize = 0; + char *sAreas, *fAreas; + + sAreas = calloc(PATH_MAX, sizeof(char)); + fAreas = calloc(PATH_MAX, sizeof(char)); + + IsDoing("List fileareas"); + if (!do_quiet) { + colour(3, 0); + printf(" Area Files MByte File Group Area name\n"); + printf("----- ----- ----- ------------ --------------------------------------------\n"); + colour(7, 0); + } + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("Can't open %s", sAreas); + if (!do_quiet) + printf("Can't open %s\n", sAreas); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + fseek(pAreas, 0, SEEK_END); + iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; + + for (i = 1; i <= iAreas; i++) { + fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&area, areahdr.recsize, 1, pAreas); + + if (area.Available) { + + sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); + + /* + * Open the file database, create new one if it doesn't excist. + */ + if ((pFile = fopen(fAreas, "r+")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + fcount = 0; + fsize = 0L; + while (fread(&file, sizeof(file), 1, pFile) == 1) { + fcount++; + fsize = fsize + file.Size; + } + fsize = fsize / 1048576; + tcount += fcount; + tsize += fsize; + + if (!do_quiet) + printf("%5d %5d %5ld %-12s %s\n", i, fcount, fsize, area.BbsGroup, area.Name); + iTotal++; + } + } + + if (!do_quiet) { + colour(3, 0); + printf("----- ----- ----- ---------------------------------------------------------\n"); + printf("%5d %5d %5ld \n", iTotal, tcount, tsize); + } + + fclose(pAreas); + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(sAreas); + free(fAreas); +} + diff --git a/mbfido/mbflist.h b/mbfido/mbflist.h new file mode 100644 index 00000000..3b494937 --- /dev/null +++ b/mbfido/mbflist.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFLIST_H_ +#define _MBFLIST_H + +void ListFileAreas(void); /* List fileareas */ + +#endif diff --git a/mbfido/mbfpack.c b/mbfido/mbfpack.c new file mode 100644 index 00000000..7d1aedc6 --- /dev/null +++ b/mbfido/mbfpack.c @@ -0,0 +1,165 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - Pack filebase + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbfpack.h" + + + +extern int do_quiet; /* Supress screen output */ +//int do_pack = FALSE; /* Pack filebase */ +//int do_check = FALSE; /* Check filebase */ +//int do_kill = FALSE; /* Kill/move old files */ +//int do_index = FALSE; /* Create request index */ +//int do_list = FALSE; /* List fileareas */ +//extern int e_pid; /* Pid of external process */ +//extern int show_log; /* Show logging */ +//time_t t_start; /* Start time */ +//time_t t_end; /* End time */ + + + + +/* + * Removes records who are marked for deletion. If there is still a file + * on disk, it will be removed too. + */ +void PackFileBase(void) +{ + FILE *fp, *pAreas, *pFile; + int i, iAreas, iAreasNew = 0; + int iTotal = 0, iRemoved = 0; + char *sAreas, *fAreas, *fTmp, fn[PATH_MAX]; + + sAreas = calloc(PATH_MAX, sizeof(char)); + fAreas = calloc(PATH_MAX, sizeof(char)); + fTmp = calloc(PATH_MAX, sizeof(char)); + + IsDoing("Pack filebase"); + if (!do_quiet) { + colour(3, 0); + printf("Packing file database...\n"); + } + + sprintf(sAreas, "%s/etc/fareas.data", getenv("MBSE_ROOT")); + + if ((pAreas = fopen (sAreas, "r")) == NULL) { + WriteError("Can't open %s", sAreas); + die(0); + } + + fread(&areahdr, sizeof(areahdr), 1, pAreas); + fseek(pAreas, 0, SEEK_END); + iAreas = (ftell(pAreas) - areahdr.hdrsize) / areahdr.recsize; + + for (i = 1; i <= iAreas; i++) { + + fseek(pAreas, ((i-1) * areahdr.recsize) + areahdr.hdrsize, SEEK_SET); + fread(&area, areahdr.recsize, 1, pAreas); + + if (area.Available && !area.CDrom) { + + if (!diskfree(CFG.freespace)) + die(101); + + if (!do_quiet) { + printf("\r%4d => %-44s", i, area.Name); + fflush(stdout); + } + Marker(); + + sprintf(fAreas, "%s/fdb/fdb%d.data", getenv("MBSE_ROOT"), i); + sprintf(fTmp, "%s/fdb/fdbtmp.data", getenv("MBSE_ROOT")); + + if ((pFile = fopen(fAreas, "r")) == NULL) { + Syslog('!', "Creating new %s", fAreas); + if ((pFile = fopen(fAreas, "a+")) == NULL) { + WriteError("$Can't create %s", fAreas); + die(0); + } + } + + if ((fp = fopen(fTmp, "a+")) == NULL) { + WriteError("$Can't create %s", fTmp); + die(0); + } + + while (fread(&file, sizeof(file), 1, pFile) == 1) { + + iTotal++; + + if ((!file.Deleted) && (strcmp(file.Name, "") != 0)) { + fwrite(&file, sizeof(file), 1, fp); + } else { + iRemoved++; + Syslog('+', "Removed file \"%s\" from area %d", file.Name, i); + sprintf(fn, "%s/%s", area.Path, file.Name); + Syslog('+', "Unlink %s result %d", fn, unlink(fn)); + /* + * If a dotted version (thumbnail) exists, remove it silently + */ + sprintf(fn, "%s/.%s", area.Path, file.Name); + unlink(fn); + } + } + + fclose(fp); + fclose(pFile); + + if ((rename(fTmp, fAreas)) == 0) { + unlink(fTmp); + chmod(fAreas, 00660); + } + iAreasNew++; + + } /* if area.Available */ + } + + fclose(pAreas); + Syslog('+', "Pack Areas [%5d] Files [%5d] Removed [%5d]", iAreasNew, iTotal, iRemoved); + + if (!do_quiet) { + printf("\r \r"); + fflush(stdout); + } + + free(fTmp); + free(sAreas); + free(fAreas); +} + + + diff --git a/mbfido/mbfpack.h b/mbfido/mbfpack.h new file mode 100644 index 00000000..f6dbe35f --- /dev/null +++ b/mbfido/mbfpack.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef _MBFPACK_H_ +#define _MBFPACK_H + +void PackFileBase(void); /* Pack / Compress File Base */ + +#endif diff --git a/mbfido/mbfutil.c b/mbfido/mbfutil.c new file mode 100644 index 00000000..609d28fb --- /dev/null +++ b/mbfido/mbfutil.c @@ -0,0 +1,222 @@ +/***************************************************************************** + * + * $Id$ + * Purpose: File Database Maintenance - utilities + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/dbcfg.h" +#include "mbfutil.h" +#include "mbfile.h" + + + +extern int do_quiet; /* Supress screen output */ +extern int e_pid; /* Pid of external process */ +extern time_t t_start; /* Start time */ +extern time_t t_end; /* End time */ +int marker = 0; /* Marker counter */ + + + +void ProgName(void) +{ + if (do_quiet) + return; + + colour(WHITE, BLACK); + printf("\nMBFILE: MBSE BBS %s File maintenance utility\n", VERSION); + colour(YELLOW, BLACK); + printf(" %s\n", COPYRIGHT); +} + + + +void die(int onsig) +{ + /* + * First check if a child is running, if so, kill it. + */ + if (e_pid) { + if ((kill(e_pid, SIGTERM)) == 0) + Syslog('+', "SIGTERM to pid %d succeeded", e_pid); + else { + if ((kill(e_pid, SIGKILL)) == 0) + Syslog('+', "SIGKILL to pid %d succeded", e_pid); + else + WriteError("$Failed to kill pid %d", e_pid); + } + + /* + * In case the child had the tty in raw mode... + */ + if (!do_quiet) + system("stty sane"); + } + + signal(onsig, SIG_IGN); + + if (onsig) { + if (onsig <= NSIG) + WriteError("$Terminated on signal %d (%s)", onsig, SigName[onsig]); + else + WriteError("Terminated with error %d", onsig); + } + + time(&t_end); + Syslog(' ', "MBFILE finished in %s", t_elapsed(t_start, t_end)); + + if (!do_quiet) { + colour(7, 0); + printf("\n"); + } + ExitClient(onsig); +} + + + +void Help(void) +{ + do_quiet = FALSE; + ProgName(); + + colour(LIGHTCYAN, BLACK); + printf("\nUsage: mbfile [command] \n\n"); + colour(LIGHTBLUE, BLACK); + printf(" Commands are:\n\n"); + colour(CYAN, BLACK); + printf(" a adopt [desc] Adopt file to area\n"); + printf(" c check Check filebase\n"); +// printf(" d delete Mark file in area for deletion\n"); +// printf(" im import Import files in current dir to area\n"); + printf(" in index Create filerequest index\n"); + printf(" k kill Kill/move old files\n"); + printf(" l list List file areas\n"); +// printf(" m move Move file from to area\n"); + printf(" p pack Pack filebase\n"); +// printf(" r rearc [file] [arc] Rearc file(s) in area\n"); + colour(LIGHTBLUE, BLACK); + printf("\n Options are:\n\n"); + colour(CYAN, BLACK); + printf(" -q -quiet Quiet mode\n"); + colour(LIGHTGRAY, BLACK); + printf("\n"); + die(0); +} + + + +void Marker(void) +{ + /* + * Keep the connection with the server alive + */ + Nopper(); + + /* + * Release system resources when running in the background + */ + if (CFG.slow_util && do_quiet) + usleep(1); + + if (do_quiet) + return; + + switch (marker) { + case 0: printf(">---"); + break; + + case 1: printf(">>--"); + break; + + case 2: printf(">>>-"); + break; + + case 3: printf(">>>>"); + break; + + case 4: printf("<>>>"); + break; + + case 5: printf("<<>>"); + break; + + case 6: printf("<<<>"); + break; + + case 7: printf("<<<<"); + break; + + case 8: printf("-<<<"); + break; + + case 9: printf("--<<"); + break; + + case 10:printf("---<"); + break; + + case 11:printf("----"); + break; + } + printf("\b\b\b\b"); + fflush(stdout); + + if (marker < 11) + marker++; + else + marker = 0; +} + + + +void DeleteVirusWork() +{ + char *buf, *temp; + + buf = calloc(PATH_MAX, sizeof(char)); + temp = calloc(PATH_MAX, sizeof(char)); + getcwd(buf, PATH_MAX); + sprintf(temp, "%s/tmp", getenv("MBSE_ROOT")); + + if (chdir(temp) == 0) { + Syslog('f', "DeleteVirusWork %s/arc", temp); + system("rm -r -f arc"); + system("mkdir arc"); + } else + WriteError("$Can't chdir to %s", temp); + + chdir(buf); + free(temp); + free(buf); +} + + diff --git a/mbfido/mbfutil.h b/mbfido/mbfutil.h new file mode 100644 index 00000000..02414d7a --- /dev/null +++ b/mbfido/mbfutil.h @@ -0,0 +1,12 @@ +/* $Id$ */ + +#ifndef _MBFUTIL_H_ +#define _MBFUTIL_H + +void ProgName(void); /* Program name header */ +void die(int onsig); /* Shutdown and cleanup */ +void Help(void); /* Show help screen */ +void Marker(void); /* Eyecatcher */ +void DeleteVirusWork(void); /* Delete unarc directory */ + +#endif diff --git a/mbfido/utic.c b/mbfido/utic.c index 5a5462c5..88ae2d54 100644 --- a/mbfido/utic.c +++ b/mbfido/utic.c @@ -1,8 +1,7 @@ /***************************************************************************** * - * File ..................: mbfido/utic.c + * $Id$ * Purpose ...............: Utilities for tic processing - * Last modification date : 26-May-2000 * ***************************************************************************** * Copyright (C) 1997-2000 @@ -80,7 +79,7 @@ int Day_Of_Year() int Rearc(char *unarc) { int i, j; - char temp[81], *cmd = NULL; + char temp[PATH_MAX], *cmd = NULL; Syslog('f', "Entering Rearc(%s)", unarc); @@ -124,10 +123,11 @@ int Rearc(char *unarc) void DeleteVirusWork() { - char *buf = NULL; - char temp[81]; + char *buf, *temp; - getcwd(buf, 128); + buf = calloc(PATH_MAX, sizeof(char)); + temp = calloc(PATH_MAX, sizeof(char)); + getcwd(buf, PATH_MAX); sprintf(temp, "%s/tmp", getenv("MBSE_ROOT")); if (chdir(temp) == 0) { @@ -138,6 +138,8 @@ void DeleteVirusWork() WriteError("$Can't chdir to %s", temp); chdir(buf); + free(temp); + free(buf); }