aboutsummaryrefslogblamecommitdiffstats
path: root/daemon/purger.c
blob: 43be168e8ae6beca80779b926c0c4ef7e126083d (plain) (tree)


























































































































































                                                                                                         
/*
 * purger.c - syslogd implementation for windows, log dir purger
 *
 * Created by Alexander Yaworsky
 *
 * THIS SOFTWARE IS NOT COPYRIGHTED
 *
 * This source code is offered for use in the public domain. You may
 * use, modify or distribute it freely.
 *
 * This code is distributed in the hope that it will be useful but
 * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
 * DISCLAIMED. This includes but is not limited to warranties of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

#include <stdio.h>
#include <windows.h>

#include <glib.h>

#include <syslog.h>
#include <syslogd.h>

static HANDLE purger_semaphore = NULL;

/******************************************************************************
 * recursive_purge
 *
 * auxiliary function for purge_log_dirs
 */
static void recursive_purge( gchar* pathname, LPFILETIME min_time )
{
    gchar *new_pathname;
    HANDLE find_handle;
    WIN32_FIND_DATA find_data;

    TRACE_ENTER( "%s\n", pathname );

    new_pathname = g_build_filename( pathname, "*", NULL );
    find_handle = FindFirstFile( new_pathname, &find_data );
    if( INVALID_HANDLE_VALUE == find_handle )
    {
        TRACE_2( "FindFirstFile(%s) error %lu\n", new_pathname, GetLastError() );
        g_free( new_pathname );
        TRACE_LEAVE( "it seems the path does not exist\n" );
        return;
    }
    g_free( new_pathname );
    do {
        if( (find_data.cFileName[0] == '.' && find_data.cFileName[1] == '\0')
            ||
            (find_data.cFileName[0] == '.'
             && find_data.cFileName[1] == '.' && find_data.cFileName[2] == '\0') )
            continue;

        new_pathname = g_build_filename( pathname, find_data.cFileName, NULL );
        if( find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
        {
            recursive_purge( new_pathname, min_time );
            if( RemoveDirectory( new_pathname ) )
            {
                TRACE( "removed %s\n", new_pathname );
            }
            else
            {
                TRACE( "failed to remove %s\n", new_pathname );
            }
        }
        else
        {
            if( CompareFileTime( min_time, &find_data.ftLastWriteTime ) > 0 )
            {
                if( DeleteFile( new_pathname ) )
                {
                    TRACE( "deleted %s\n", new_pathname );
                }
                else
                {
                    TRACE( "failed to delete %s\n", new_pathname );
                }
            }
        }
        g_free( new_pathname );
    } while( FindNextFile( find_handle, &find_data ) );
    FindClose( find_handle );

    TRACE_LEAVE( "done\n" );
}

/******************************************************************************
 * purge_log_dirs
 */
void purge_log_dirs()
{
    GList *item;

    TRACE_ENTER( "\n" );
    if( WaitForSingleObject( purger_semaphore, 0 ) != WAIT_OBJECT_0 )
    {
        TRACE_LEAVE( "done; another thread is active\n" );
        return;
    }
    for( item = purger_dirs; item; item = item->next )
    {
        struct purger_dir *p = item->data;
        gchar *pathname = make_absolute_log_pathname( p->directory );
        FILETIME min_time;
        long long min_time_64;

        GetSystemTimeAsFileTime( &min_time );
        min_time_64 = (((long long) min_time.dwHighDateTime) << 32) + (long long) min_time.dwLowDateTime;
        min_time_64 -= ((long long) p->keep_days) * ((long long) (24 * 3600)) * (long long) 10000000;
        min_time.dwHighDateTime = min_time_64 >> 32;
        min_time.dwLowDateTime = min_time_64;

        recursive_purge( pathname, &min_time );
        g_free( pathname );
    }
    ReleaseSemaphore( purger_semaphore, 1, NULL );
    TRACE_LEAVE( "done\n" );
}

/******************************************************************************
 * init_purger
 */
gboolean init_purger()
{
    gboolean ret = FALSE;

    TRACE_ENTER( "\n" );

    purger_semaphore = CreateSemaphore( NULL, 1, 1, NULL );
    if( !purger_semaphore )
    {
        ERR( "Cannot create semaphore; error %lu\n", GetLastError() );
        goto done;
    }
    ret = TRUE;

done:
    TRACE_LEAVE( "done; ret=%d\n", ret );
    return ret;
}

/******************************************************************************
 * fini_purger
 */
void fini_purger()
{
    TRACE_ENTER( "\n" );
    if( purger_semaphore ) CloseHandle( purger_semaphore );
    TRACE_LEAVE( "done\n" );
}