Logo Search packages:      
Sourcecode: bfbtester version File versions  Download package

tempfiles.c

/*
    BFBTester -- Brute Force Binary Tester
    Copyright (C) 2000 Mike Heffner <mheffner@vt.edu>

    This program 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 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      $Id: tempfiles.c,v 1.4.2.1 2001/01/22 05:31:12 fesnel Exp $
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/time.h>
#include <dirent.h>


#include "datatypes.h"
#include "tempfiles.h"
#include "utils.h"


typedef struct _file_entry FileEntry;
struct _file_entry {

      char        *filename;  /* excludes leading directories */

      struct timeval    tm;

      int               statd;
#ifdef SOLARIS
      uint32_t    fileno;
#else
      u_int32_t   fileno;
#endif /* SOLARIS */
      struct stat sb;

      FileEntry   *next;
      FileEntry   *prev;

};


typedef struct _tempfile_watch_request TempFileRequest;
struct _tempfile_watch_request {

      pthread_mutex_t   mutex;
      pthread_cond_t    cond;
      int   count;      /* Number of requests - normally 0 or 1 */
      int status; /* 0 - none, 1 - start up, 2 - running, 3 - shutting down */

      TempfileCB  create_cb;  /* creation call back */
      TempfileCB  remove_cb;  /* remove call back */
      void        *cb_data;   /* user data */
};

static int initialized = FALSE;     /* Set to true if we are using tempfile
                                                 * monitoring
                                                 */
static FileEntry *head = NULL;
static FileEntry *tail = NULL;
static TempFileRequest request = { PTHREAD_MUTEX_INITIALIZER, 
                                                   PTHREAD_COND_INITIALIZER,
                                                   0, 0, NULL, NULL, NULL };

static int
isNew(struct dirent *entry)
{
      FileEntry *entries = head;

#ifdef SOLARIS
      while(entries && entry->d_ino > entries->fileno)
#else
      while(entries && entry->d_fileno > entries->fileno)
#endif /* SOLARIS */
            entries = entries->next;

      if (entries &&
#ifdef SOLARIS
            entries->fileno == entry->d_ino
#else
            entries->fileno == entry->d_fileno
#endif
            )
            return FALSE;
      else
            return TRUE;
}

static void
addFile(struct dirent *entry, struct timeval tm)
{
      FileEntry *new;

      new = xmalloc(sizeof(FileEntry));
      
      new->filename = strdup(entry->d_name);
      new->tm = tm;
#ifdef SOLARIS
      new->fileno = entry->d_ino;
#else
      new->fileno = entry->d_fileno;
#endif /* SOLARIS */
      new->next = NULL;
      new->prev = NULL;

      if (head == NULL) /* tail also NULL */
            head = tail = new;
      else if (new->fileno < head->fileno) {
            head->prev = new;
            new->next = head;
            head = new;
      } else if (new->fileno > tail->fileno) {
            new->prev = tail;
            tail->next = new;
            tail = new;
      } else {
            FileEntry *temp = head;
            while (new->fileno > temp->fileno) temp = temp->next;
            temp->prev->next = new;
            new->prev = temp->prev;
            new->next = temp;
            temp->prev = new;
      }
      /* call creation callback */
      if (request.create_cb && request.count
            && (request.status == 2 || request.status == 3))
            (*request.create_cb)(new->filename, &new->sb, request.cb_data);
}

static void
updateFile(struct dirent *entry, struct timeval tm)
{
      FileEntry *temp = head;

      /* At this point we know entry is in the list somewhere */
      while (temp->fileno !=
#ifdef SOLARIS
               entry->d_ino
#else
               entry->d_fileno
#endif
            ) temp = temp->next;

      temp->tm = tm;
}

/* Unlinks from list -- does NOT free() node */
static void
removeFile(FileEntry *entry)
{
      if (entry->prev && entry->next) {
            entry->prev->next = entry->next;
            entry->next->prev = entry->prev;
      } else {
            if (head == entry) {
                  if (entry->next)
                        entry->next->prev = NULL;
                  else /* one item list */
                        tail = NULL;
                  head = entry->next;
            } else { /* (tail == entry) */
                  entry->prev->next = NULL;
                  tail = entry->prev;
            }
      }
      /* call deletion callback */
      if (request.remove_cb && request.count
            && (request.status == 2 || request.status == 3))
            (*request.remove_cb)(entry->filename, &entry->sb, request.cb_data);
}

/* Free memory used by file */
static void
deleteFile(FileEntry *entry)
{
      if (entry->filename) free(entry->filename);
      free(entry);
}

static void
AddOrUpdate(struct dirent *entry, struct timeval tm)
{
      /* Add if entry is new or tag it as still available */
      if (isNew(entry))
            addFile(entry, tm);
      else
            updateFile(entry, tm);
}

static void
tempfile_scandir(DIR *dir)
{
      struct dirent     entry;
      struct dirent     *result;
      int ret;
      struct timeval tm;
      FileEntry *temp, *dead;

      gettimeofday(&tm, NULL);

      ret = readdir_r(dir, &entry, &result);
      while (ret == 0 && result != NULL) {
            AddOrUpdate(result, tm);
            ret = readdir_r(dir, &entry, &result);
      }
      /* Scan for files that were removed (ie. not updated) */
      if (ret == 0) {
            temp = head;
            while (temp) {
                  if (memcmp(&temp->tm, &tm, sizeof(struct timeval)) != 0) {
                        dead = temp;
                        temp = temp->next;
                        removeFile(dead);
                        deleteFile(dead);
                  } else
                        temp = temp->next;
            }
      }
      rewinddir(dir); /* rewinds for next time */
}

static void
tempfile_request_startup(void)
{
      /* Already have mutex locked */
      request.status = 2;
      pthread_cond_signal(&request.cond);
}

static void
tempfile_request_shutdown(void)
{
      /* Already have mutex locked */
      request.status = 0;
      pthread_cond_signal(&request.cond);
}

static void *
tempfile_watch(void *data)
{

      char *dirname;
      DIR   *dir;
      int   lasttime = 0;

      if (!(dirname = getenv("BFBT_TMPDIR")))
            dirname = "/tmp"; 
      
      initialized = TRUE;
      if ((dir = opendir(dirname)) == NULL)
            bfbt_message(MSG_TYPE_ERROR_ABORT, "opendir: %s failed", dirname);
      while(1){
            
            tempfile_scandir(dir);

            pthread_mutex_lock(&request.mutex);
            if (request.status == 1 || request.status == 3) {
                  if (request.status == 1) {    /* starting a new request */
                        if (lasttime) {
                              tempfile_request_startup();
                              lasttime = 0;
                        } else
                              lasttime = 1;
                  } else /* request.status == 3 */ {  /* shutting down request */
                        if (lasttime) {
                              tempfile_request_shutdown();
                              lasttime = 0;
                        } else
                              lasttime = 1;
                  }
            } else
                  while (request.status == 0)
                        pthread_cond_wait(&request.cond, &request.mutex);
            pthread_mutex_unlock(&request.mutex);
            pthread_testcancel();
      }
      return NULL;
}

int
tempfile_request_add(TempfileCB     create, TempfileCB remove, void *cbdata)
{
      if (!initialized)
            return 0;
      pthread_mutex_lock(&request.mutex);
      if (request.count || request.status != 0)
            return -1;
      request.count = 1;
      request.status = 1;
      pthread_cond_signal(&request.cond);
      while (request.status == 1)
            pthread_cond_wait(&request.cond, &request.mutex);
      request.create_cb = create;
      request.remove_cb = remove;
      request.cb_data = cbdata;
      pthread_mutex_unlock(&request.mutex);
      return 0;
}

int
tempfile_request_subtract(void)
{
      if (!initialized)
            return 0;
      pthread_mutex_unlock(&request.mutex);
      if (!request.count || request.status != 2)
            return -1;
      request.status = 3;
      while (request.status == 3)
            pthread_cond_wait(&request.cond, &request.mutex);
      request.count--;
      request.create_cb = NULL;
      request.remove_cb = NULL;
      request.cb_data = NULL;
      pthread_mutex_unlock(&request.mutex);
      return 0;
}

void
tempfile_start(THREAD_DATA *data)
{
      if (pthread_create(&data->tempfile_thread, NULL, tempfile_watch, NULL) != 0)
            bfbt_message(MSG_TYPE_ERRNO_ABORT, "tempfile thread create");
}

Generated by  Doxygen 1.6.0   Back to index