1 /******************************************************************************
2  * HTICK --- FTN Ticker / Request Processor
3  ******************************************************************************
4  * clean.c : htick cleaning functionality
5  *
6  * Copyright (C) 2002 by
7  *
8  * Max Chernogor
9  *
10  * Fido:      2:464/108@fidonet
11  * Internet:  <mihz@mail.ru>,<mihz@ua.fm>
12  *
13  * This file is part of HTICK
14  *
15  * This is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published
17  * by the Free Software Foundation; either version 2, or (at your option)
18  * any later version.
19  *
20  * HTICK is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with HTICK; see the file COPYING.  If not, write to the Free Software
27  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA
28  *
29  * See also http://www.gnu.org
30  *****************************************************************************
31  * $Id$
32  */
33 
34 /* Functions call tree.
35 
36   Purge()
37   +--- cleanPassthroughDir() +--- addFileToTree()
38   |
39   +--- purgeFileEchos()
40   |
41   +--- purgeOldTics()
42  */
43 
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 
49 
50 #include <huskylib/huskylib.h>
51 
52 #include <huskylib/log.h>
53 #include <huskylib/xstr.h>
54 #include <fidoconf/common.h>
55 #include <huskylib/dirlayer.h>
56 #include <huskylib/tree.h>
57 #include <areafix/areafix.h>
58 
59 #include "toss.h"
60 #include "htick.h"
61 #include "global.h"
62 #include "fcommon.h"
63 
64 
65 static tree *fileTree = NULL;
66 
htick_compareEntries(char * p_e1,char * p_e2)67 int htick_compareEntries( char *p_e1, char *p_e2 )
68 {
69   if( p_e1 && p_e2 )
70     return stricmp( p_e1, p_e2 );
71 
72   w_log( LL_CRIT,
73          __FILE__
74          ":: Parameter is NULL: htick_compareEntries(%s,%s). This is serious error in program, please report to developers.",
75          p_e1 ? "p_e1" : "NULL", p_e2 ? "p_e2" : "NULL" );
76   return -1;
77 }
78 
htick_deleteEntry(char * p_e1)79 int htick_deleteEntry( char *p_e1 )
80 {
81   nfree( p_e1 );
82   return 1;
83 }
84 
addFileToTree(char * dir,char * filename)85 void addFileToTree( char *dir, char *filename )
86 {
87   s_ticfile tic;
88 
89   if( !dir || !filename )
90   {
91     w_log( LL_CRIT,
92            __FILE__
93            ":: Parameter is NULL: addFileToTree(%s,%s). This is serious error in program, please report to developers.",
94            dir ? "dir" : "NULL", filename ? "filename" : "NULL" );
95     return;
96   }
97 
98   if( patimat( filename, "*.TIC" ) == 1 )
99   {
100     char *ticfile = NULL;
101     e_parseTic_result ticres;
102 
103     xstrscat( &ticfile, dir, filename, NULL );
104     ticres = parseTic( ticfile, &tic );
105     if( ( ticres == parseTic_success ) && ( tic.file ) )
106     {
107       tree_add( &fileTree, htick_compareEntries, sstrdup( tic.file ), htick_deleteEntry );
108     }
109     if( ticres != parseTic_error )
110       disposeTic( &tic );
111     nfree( ticfile );
112   }
113 }
114 
cleanPassthroughDir(void)115 void cleanPassthroughDir( void )
116 {
117   husky_DIR *dir;
118   char *filename;
119   char *ticfile = NULL;
120 
121   w_log( LL_FUNC, "cleanPassthroughDir(): begin" );
122 
123   tree_init( &fileTree, 1 );
124 
125   /* check busyFileDir */
126   if( direxist( config->busyFileDir ) )
127   {
128     dir = husky_opendir( config->busyFileDir );
129     if( dir != NULL )
130     {
131       while( ( filename = husky_readdir( dir ) ) != NULL )
132       {
133         addFileToTree( config->busyFileDir, filename );
134       }
135       husky_closedir( dir );
136     }
137   }
138   /* check separateBundles dirs (does anybody use this?) */
139   if( config->separateBundles )
140   {
141     UINT i;
142     char tmpdir[256];
143     int pcnt;
144     hs_addr *aka;
145 
146     for( i = 0; i < config->linkCount; i++ )
147     {
148       if( config->links[i]->hisPackAka.zone != 0 )
149         pcnt = 0;
150       else
151         pcnt = 1;
152       aka = &( config->links[i]->hisAka );
153       do
154       {
155         if( createOutboundFileNameAka( config->links[i], flNormal, FLOFILE, aka ) == 0 )
156         {
157           strcpy( tmpdir, config->links[i]->floFile );
158           sprintf( strrchr( tmpdir, '.' ), ".sep" );
159           if( direxist( tmpdir ) )
160           {
161             sprintf( tmpdir + strlen( tmpdir ), "%c", PATH_DELIM );
162             dir = husky_opendir( tmpdir );
163             if( dir == NULL )
164               continue;
165 
166             while( ( filename = husky_readdir( dir ) ) != NULL )
167             {
168               addFileToTree( tmpdir, filename );
169             }                   /* while */
170             husky_closedir( dir );
171             if( config->links[i]->bsyFile )
172             {
173               remove( config->links[i]->bsyFile );
174               nfree( config->links[i]->bsyFile );
175             }
176             nfree( config->links[i]->floFile );
177           }
178         }
179         if( pcnt == 1 )
180         {
181           pcnt = 0;
182           aka = &( config->links[i]->hisPackAka );
183         }
184       } while( pcnt != 0 );
185     }
186   }
187   /* check ticOutbound */
188   dir = husky_opendir( config->ticOutbound );
189   if( dir != NULL )
190   {
191     while( ( filename = husky_readdir( dir ) ) != NULL )
192     {
193       addFileToTree( config->ticOutbound, filename );
194     }
195     husky_closedir( dir );
196   }
197   /* purge passFileAreaDir */
198   dir = husky_opendir( config->passFileAreaDir );
199   if( dir != NULL )
200   {
201     while( ( filename = husky_readdir( dir ) ) != NULL )
202     {
203       if( patimat( filename, "*.TIC" ) != 1 )
204       {
205         xstrscat( &ticfile, config->passFileAreaDir, filename, NULL );
206 
207         if( direxist( ticfile ) )
208         {                       /*  do not touch dirs */
209           nfree( ticfile );
210           continue;
211         }
212         if( !tree_srch( &fileTree, htick_compareEntries, filename ) )
213         {
214           w_log( LL_DEL, "Remove file %s from passthrough dir", ticfile );
215           remove( ticfile );
216           nfree( ticfile );
217           continue;
218         }
219         nfree( ticfile );
220       }
221     }
222     husky_closedir( dir );
223   }
224   tree_mung( &fileTree, htick_deleteEntry );
225 
226   w_log( LL_FUNC, "cleanPassthroughDir(): end" );
227 }
228 
purgeFileEchos()229 void purgeFileEchos(  )
230 {
231   UINT i;
232   char *filename = NULL;
233   time_t tnow;
234 
235   husky_DIR *dir;
236   char *file;
237   struct stat st;
238 
239   w_log( LL_FUNC, "purgeFileEchos()" );
240 
241   time( &tnow );
242 
243   for( i = 0; i < config->fileAreaCount; i++ )
244   {
245     if( config->fileAreas[i].purge == 0 )
246       continue;
247     w_log( LL_INFO, "Cleaning %s ...", config->fileAreas[i].areaName );
248     dir = husky_opendir( config->fileAreas[i].fileName );
249     if( dir == NULL )
250       continue;
251 
252     while( ( file = husky_readdir( dir ) ) != NULL )
253     {
254       if( patimat( file, "*.BBS" ) == 1 )
255         continue;
256 
257       xstrscat( &filename, config->fileAreas[i].fileName, file, NULL );
258       if( direxist( filename ) )
259       {                         /*  do not touch dirs */
260         nfree( filename );
261         continue;
262       }
263       memset( &st, 0, sizeof( st ) );
264       stat( filename, &st );
265       if( st.st_mtime + ( time_t ) ( config->fileAreas[i].purge * 86400 ) > tnow )
266       {
267         nfree( filename );
268         continue;
269       }
270       w_log( LL_INFO, "Deleting file %s that is %d days old", file,
271              ( tnow - st.st_mtime ) / 86400 );
272       removeFileMask( config->fileAreas[i].fileName, file );
273       nfree( filename );
274     }
275     husky_closedir( dir );
276   }
277 
278   w_log( LL_FUNC, "purgeFileEchos(): end" );
279 }
280 
purgeOldTics()281 void purgeOldTics(  )
282 {
283   UINT i;
284   s_savetic *savetic;
285   char *filename = NULL;
286   time_t tnow;
287 
288   husky_DIR *dir;
289   char *file;
290   struct stat st;
291 
292   w_log( LL_FUNC, "purgeOldTics()" );
293 
294   time( &tnow );
295 
296   for( i = 0; i < config->saveTicCount; i++ )
297   {
298     savetic = &( config->saveTic[i] );
299     if( savetic->days2save == 0 )
300     {
301       continue;
302     }
303     w_log( LL_INFO, "Cleaning %s ...", savetic->pathName );
304     dir = husky_opendir( savetic->pathName );
305     if( dir == NULL )
306     {
307       continue;
308     }
309     while( ( file = husky_readdir( dir ) ) != NULL )
310     {
311       if( patimat( file, "*.TIC" ) == 0 )
312         continue;
313 
314       xstrscat( &filename, savetic->pathName, file, NULL );
315       if( direxist( filename ) )
316       {                         /*  do not touch dirs */
317         nfree( filename );
318         continue;
319       }
320       memset( &st, 0, sizeof( st ) );
321       stat( filename, &st );
322       if( st.st_mtime + ( time_t ) ( savetic->days2save * 86400 ) > tnow )
323       {
324         nfree( filename );
325         continue;
326       }
327       w_log( LL_INFO, "Deleting file %s that is %d days old", file,
328              ( tnow - st.st_mtime ) / 86400 );
329       removeFileMask( savetic->pathName, file );
330       nfree( filename );
331     }
332     husky_closedir( dir );
333   }
334   w_log( LL_FUNC, "purgeOldTics(): end" );
335 }
336 
Purge(void)337 void Purge( void )
338 {
339   w_log( LL_INFO, "Clean (purging files in passthrough dir) ..." );
340   cleanPassthroughDir(  );
341   w_log( LL_INFO, "Clean FileEchos" );
342   purgeFileEchos(  );
343   w_log( LL_INFO, "Clean old tics in savetic dirs" );
344   purgeOldTics(  );
345 }
346