Move exclusive file access functions into their own source file (exfile.c)
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 6 Dec 2014 02:57:24 +0000 (21:57 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 6 Dec 2014 02:57:24 +0000 (21:57 -0500)
src/include/exfile.h [new file with mode: 0644]
src/include/log.h
src/main/exfile.c [new file with mode: 0644]
src/main/libfreeradius-server.mk
src/main/log.c
src/modules/rlm_detail/rlm_detail.c
src/modules/rlm_linelog/rlm_linelog.c
src/modules/rlm_sql/rlm_sql.c
src/modules/rlm_sql/rlm_sql.h
src/modules/rlm_sql/sql.c

diff --git a/src/include/exfile.h b/src/include/exfile.h
new file mode 100644 (file)
index 0000000..3cc4dbd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Lesser General Public
+ *   License as published by the Free Software Foundation; either
+ *   version 2.1 of the License, or (at your option) any later version.
+ *
+ *   This library 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
+ *   Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef EXFILE_H
+#define EXFILE_H
+/*
+ * $Id$
+ *
+ * @file exfile.h
+ * @brief Functions for managing concurrent file access.
+ *
+ * @copyright 2014 The FreeRADIUS server project
+ */
+RCSIDH(exfile_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ *     Multiple threads logging to one or more files.
+ */
+typedef struct exfile_t exfile_t;
+
+exfile_t *exfile_init(TALLOC_CTX *ctx, uint32_t entries, uint32_t idle);
+int exfile_open(exfile_t *lf, char const *filename, mode_t permissions);
+int exfile_close(exfile_t *lf, int fd);
+int exfile_unlock(exfile_t *lf, int fd);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
index 64df1cd..08c378e 100644 (file)
@@ -107,16 +107,6 @@ void       radlog_request_marker(log_type_t type, log_lvl_t lvl, REQUEST *request,
 void   fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg);
 
 /*
- *     Multiple threads logging to one or more files.
- */
-typedef struct fr_logfile_t fr_logfile_t;
-
-fr_logfile_t *fr_logfile_init(TALLOC_CTX *ctx);
-int fr_logfile_open(fr_logfile_t *lf, char const *filename, mode_t permissions);
-int fr_logfile_close(fr_logfile_t *lf, int fd);
-int fr_logfile_unlock(fr_logfile_t *lf, int fd);
-
-/*
  *     Logging macros.
  *
  *     For server code, do not call radlog, vradlog et al directly, use one of the logging macros instead.
diff --git a/src/main/exfile.c b/src/main/exfile.c
new file mode 100644 (file)
index 0000000..e49952b
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ *   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/*
+ * $Id$
+ *
+ * @file exfile.c
+ * @brief Allow multiple threads to write to the same set of files.
+ *
+ * @author Alan DeKok <aland@freeradius.org>
+ * @copyright 2014  The FreeRADIUS server project
+ */
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/exfile.h>
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+typedef struct exfile_entry_t {
+       int             fd;             //!< File descriptor associated with an entry.
+       int             dup;
+       uint32_t        hash;           //!< Hash for cheap comparison.
+       time_t          last_used;      //!< Last time the entry was used.
+       char            *filename;      //!< Filename.
+} exfile_entry_t;
+
+
+struct exfile_t {
+       uint32_t        max_entries;    //!< How many file descriptors we keep track of.
+       uint32_t        max_idle;       //!< Maximum idle time for a descriptor.
+
+#ifdef HAVE_PTHREAD_H
+       pthread_mutex_t mutex;
+#endif
+       exfile_entry_t *entries;
+};
+
+
+#ifdef HAVE_PTHREAD_H
+#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
+#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
+
+#else
+/*
+ *     This is easier than ifdef's throughout the code.
+ */
+#define PTHREAD_MUTEX_LOCK(_x)
+#define PTHREAD_MUTEX_UNLOCK(_x)
+#endif
+
+static int _exfile_free(exfile_t *ef)
+{
+       uint32_t i;
+
+       PTHREAD_MUTEX_LOCK(&ef->mutex);
+
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) continue;
+
+               close(ef->entries[i].fd);
+       }
+
+       PTHREAD_MUTEX_UNLOCK(&ef->mutex);
+
+#ifdef HAVE_PTHREAD_H
+       pthread_mutex_destroy(&ef->mutex);
+#endif
+
+       return 0;
+}
+
+
+/** Initialize a way for multiple threads to log to one or more files.
+ *
+ * @param ctx The talloc context
+ * @param max_entries Max file descriptors to cache, and manage locks for.
+ * @param max_idle Maximum time a file descriptor can be idle before it's closed.
+ * @return the new context, or NULL on error.
+ */
+exfile_t *exfile_init(TALLOC_CTX *ctx, uint32_t max_entries, uint32_t max_idle)
+{
+       exfile_t *ef;
+
+       ef = talloc_zero(ctx, exfile_t);
+       if (!ef) return NULL;
+
+       ef->entries = talloc_zero_array(ef, exfile_entry_t, max_entries);
+       if (!ef->entries) {
+               talloc_free(ef);
+               return NULL;
+       }
+
+#ifdef HAVE_PTHREAD_H
+       if (pthread_mutex_init(&ef->mutex, NULL) != 0) {
+               talloc_free(ef);
+               return NULL;
+       }
+#endif
+
+       ef->max_entries = max_entries;
+       ef->max_idle = max_idle;
+
+       talloc_set_destructor(ef, _exfile_free);
+
+       return ef;
+}
+
+/** Open a new log file, or maybe an existing one.
+ *
+ * When multithreaded, the FD is locked via a mutex.  This way we're
+ * sure that no other thread is writing to the file.
+ *
+ * @param ef The logfile context returned from exfile_init().
+ * @param filename the file to open.
+ * @param permissions to use.
+ * @return an FD used to write to the file, or -1 on error.
+ */
+int exfile_open(exfile_t *ef, char const *filename, mode_t permissions)
+{
+       uint32_t i;
+       uint32_t hash;
+       time_t now = time(NULL);
+       struct stat st;
+
+       if (!ef || !filename) return -1;
+
+       hash = fr_hash_string(filename);
+
+       PTHREAD_MUTEX_LOCK(&ef->mutex);
+
+       /*
+        *      Clean up old entries.
+        */
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) continue;
+               if ((ef->entries[i].last_used + ef->max_idle) < now) {
+                       /*
+                        *      This will block forever if a thread is
+                        *      doing something stupid.
+                        */
+                       TALLOC_FREE(ef->entries[i].filename);
+                       close(ef->entries[i].fd);
+               }
+       }
+
+       /*
+        *      Find the matching entry.
+        */
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) continue;
+
+               if (ef->entries[i].hash == hash) {
+                       /*
+                        *      Same hash but different filename.  Give up.
+                        */
+                       if (strcmp(ef->entries[i].filename, filename) != 0) {
+                               PTHREAD_MUTEX_UNLOCK(&ef->mutex);
+                               return -1;
+                       }
+                       /*
+                        *      Someone else failed to create the entry.
+                        */
+                       if (!ef->entries[i].filename) {
+                               PTHREAD_MUTEX_UNLOCK(&ef->mutex);
+                               return -1;
+                       }
+                       goto do_return;
+               }
+       }
+
+       /*
+        *      Find an unused entry
+        */
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) break;
+       }
+
+       if (i >= ef->max_entries) {
+               fr_strerror_printf("Too many different filenames");
+               PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+               return -1;
+       }
+
+       /*
+        *      Create a new entry.
+        */
+
+       ef->entries[i].hash = hash;
+       ef->entries[i].filename = talloc_strdup(ef->entries, filename);
+       ef->entries[i].fd = -1;
+
+       ef->entries[i].fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, permissions);
+       if (ef->entries[i].fd < 0) {
+               mode_t dirperm;
+               char *p, *dir;
+
+               /*
+                *      Maybe the directory doesn't exist.  Try to
+                *      create it.
+                */
+               dir = talloc_strdup(ef, filename);
+               if (!dir) goto error;
+               p = strrchr(dir, FR_DIR_SEP);
+               if (!p) {
+                       fr_strerror_printf("No '/' in '%s'", filename);
+                       goto error;
+               }
+               *p = '\0';
+
+               /*
+                *      Ensure that the 'x' bit is set, so that we can
+                *      read the directory.
+                */
+               dirperm = permissions;
+               if ((dirperm & 0600) != 0) dirperm |= 0100;
+               if ((dirperm & 0060) != 0) dirperm |= 0010;
+               if ((dirperm & 0006) != 0) dirperm |= 0001;
+
+               if (rad_mkdir(dir, dirperm) < 0) {
+                       fr_strerror_printf("Failed to create directory %s: %s",
+                                          dir, strerror(errno));
+                       talloc_free(dir);
+                       goto error;
+               }
+               talloc_free(dir);
+
+               ef->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions);
+               if (ef->entries[i].fd < 0) {
+                       fr_strerror_printf("Failed to open file %s: %s",
+                                          filename, strerror(errno));
+                       goto error;
+               } /* else fall through to creating the rest of the entry */
+       } /* else the file was already opened */
+
+do_return:
+       /*
+        *      Lock from the start of the file.
+        */
+       if (lseek(ef->entries[i].fd, 0, SEEK_SET) < 0) {
+               fr_strerror_printf("Failed to seek in file %s: %s", filename, strerror(errno));
+
+       error:
+               ef->entries[i].hash = 0;
+               TALLOC_FREE(ef->entries[i].filename);
+               close(ef->entries[i].fd);
+               ef->entries[i].fd = -1;
+
+               PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+               return -1;
+       }
+
+       if (rad_lockfd(ef->entries[i].fd, 0) < 0) {
+               fr_strerror_printf("Failed to lock file %s: %s", filename, strerror(errno));
+               goto error;
+       }
+
+       /*
+        *      Maybe someone deleted the file while we were waiting
+        *      for the lock.  If so, re-open it.
+        */
+       if (fstat(ef->entries[i].fd, &st) < 0) {
+               fr_strerror_printf("Failed to stat file %s: %s", filename, strerror(errno));
+               goto error;
+       }
+
+       if (st.st_nlink == 0) {
+               close(ef->entries[i].fd);
+               ef->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions);
+               if (ef->entries[i].fd < 0) {
+                       fr_strerror_printf("Failed to open file %s: %s",
+                                          filename, strerror(errno));
+                       goto error;
+               }
+       }
+
+       /*
+        *      Seek to the end of the file before returning the FD to
+        *      the caller.
+        */
+       lseek(ef->entries[i].fd, 0, SEEK_END);
+
+       /*
+        *      Return holding the mutex for the entry.
+        */
+       ef->entries[i].last_used = now;
+       ef->entries[i].dup = dup(ef->entries[i].fd);
+       if (ef->entries[i].dup < 0) {
+               fr_strerror_printf("Failed calling dup(): %s",
+                                  strerror(errno));
+               goto error;
+       }
+
+       return ef->entries[i].dup;
+}
+
+/** Close the log file.  Really just return it to the pool.
+ *
+ * When multithreaded, the FD is locked via a mutex.  This way we're
+ * sure that no other thread is writing to the file.  This function
+ * will unlock the mutex, so that other threads can write to the file.
+ *
+ * @param ef The logfile context returned from exfile_init()
+ * @param fd the FD to close (i.e. return to the pool)
+ * @return 0 on success, or -1 on error
+ */
+int exfile_close(exfile_t *ef, int fd)
+{
+       uint32_t i;
+
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) continue;
+
+               /*
+                *      Unlock the bytes that we had previously locked.
+                */
+               if (ef->entries[i].dup == fd) {
+                       (void) rad_unlockfd(ef->entries[i].dup, 0);
+                       close(ef->entries[i].dup); /* releases the fcntl lock */
+                       ef->entries[i].dup = -1;
+
+                       PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+                       return 0;
+               }
+       }
+
+       PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+
+       fr_strerror_printf("Attempt to unlock file which does not exist");
+       return -1;
+}
+
+int exfile_unlock(exfile_t *ef, int fd)
+{
+       uint32_t i;
+
+       for (i = 0; i < ef->max_entries; i++) {
+               if (!ef->entries[i].filename) continue;
+
+               if (ef->entries[i].dup == fd) {
+                       ef->entries[i].dup = -1;
+                       PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+                       return 0;
+               }
+       }
+
+       PTHREAD_MUTEX_UNLOCK(&(ef->mutex));
+
+       fr_strerror_printf("Attempt to unlock file which does not exist");
+       return -1;
+}
index bc939b3..63370e0 100644 (file)
@@ -3,6 +3,7 @@ TARGET  := libfreeradius-server.a
 SOURCES        :=      conffile.c \
                evaluate.c \
                exec.c \
+               exfile.c \
                log.c \
                parser.c \
                map.c \
index c2ac515..e1f0eb1 100644 (file)
@@ -844,339 +844,3 @@ void fr_canonicalize_error(TALLOC_CTX *ctx, char **sp, char **text, ssize_t slen
        *text = value;
 }
 
-
-typedef struct fr_logfile_entry_t {
-       int             fd;
-       int             dup;
-       uint32_t        hash;
-       time_t          last_used;
-       char            *filename;
-} fr_logfile_entry_t;
-
-
-struct fr_logfile_t {
-       uint32_t max_entries;
-#ifdef HAVE_PTHREAD_H
-       pthread_mutex_t mutex;
-#endif
-       fr_logfile_entry_t *entries;
-};
-
-
-#ifdef HAVE_PTHREAD_H
-#define PTHREAD_MUTEX_LOCK pthread_mutex_lock
-#define PTHREAD_MUTEX_UNLOCK pthread_mutex_unlock
-
-#else
-/*
- *     This is easier than ifdef's throughout the code.
- */
-#define PTHREAD_MUTEX_LOCK(_x)
-#define PTHREAD_MUTEX_UNLOCK(_x)
-#endif
-
-static int _logfile_free(fr_logfile_t *lf)
-{
-       uint32_t i;
-
-       PTHREAD_MUTEX_LOCK(&lf->mutex);
-
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) continue;
-
-               close(lf->entries[i].fd);
-       }
-
-       PTHREAD_MUTEX_UNLOCK(&lf->mutex);
-
-#ifdef HAVE_PTHREAD_H
-       pthread_mutex_destroy(&lf->mutex);
-#endif
-
-       return 0;
-}
-
-
-/** Initialize a way for multiple threads to log to one or more files.
- *
- * @param ctx The talloc context
- * @return the new context, or NULL on error.
- */
-fr_logfile_t *fr_logfile_init(TALLOC_CTX *ctx)
-{
-       fr_logfile_t *lf;
-
-       lf = talloc_zero(ctx, fr_logfile_t);
-       if (!lf) return NULL;
-
-       lf->entries = talloc_zero_array(lf, fr_logfile_entry_t, 64);
-       if (!lf->entries) {
-               talloc_free(lf);
-               return NULL;
-       }
-
-#ifdef HAVE_PTHREAD_H
-       if (pthread_mutex_init(&lf->mutex, NULL) != 0) {
-               talloc_free(lf);
-               return NULL;
-       }
-#endif
-
-       lf->max_entries = 64;
-
-       talloc_set_destructor(lf, _logfile_free);
-
-       return lf;
-}
-
-
-/** Open a new log file, or maybe an existing one.
- *
- * When multithreaded, the FD is locked via a mutex.  This way we're
- * sure that no other thread is writing to the file.
- *
- * @param lf The logfile context returned from fr_logfile_init().
- * @param filename the file to open.
- * @param permissions to use.
- * @return an FD used to write to the file, or -1 on error.
- */
-int fr_logfile_open(fr_logfile_t *lf, char const *filename, mode_t permissions)
-{
-       uint32_t i;
-       uint32_t hash;
-       time_t now = time(NULL);
-       struct stat st;
-
-       if (!lf || !filename) return -1;
-
-       hash = fr_hash_string(filename);
-
-       PTHREAD_MUTEX_LOCK(&lf->mutex);
-
-       /*
-        *      Clean up old entries.
-        */
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) continue;
-
-               /*
-                *      FIXME: make this configurable?
-                */
-               if ((lf->entries[i].last_used + 30) < now) {
-                       /*
-                        *      This will block forever if a thread is
-                        *      doing something stupid.
-                        */
-                       TALLOC_FREE(lf->entries[i].filename);
-                       close(lf->entries[i].fd);
-               }
-       }
-
-       /*
-        *      Find the matching entry.
-        */
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) continue;
-
-               if (lf->entries[i].hash == hash) {
-                       /*
-                        *      Same hash but different filename.  Give up.
-                        */
-                       if (strcmp(lf->entries[i].filename, filename) != 0) {
-                               PTHREAD_MUTEX_UNLOCK(&lf->mutex);
-                               return -1;
-                       }
-                       /*
-                        *      Someone else failed to create the entry.
-                        */
-                       if (!lf->entries[i].filename) {
-                               PTHREAD_MUTEX_UNLOCK(&lf->mutex);
-                               return -1;
-                       }
-                       goto do_return;
-               }
-       }
-
-       /*
-        *      Find an unused entry
-        */
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) break;
-       }
-
-       if (i >= lf->max_entries) {
-               fr_strerror_printf("Too many different filenames");
-               PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-               return -1;
-       }
-
-       /*
-        *      Create a new entry.
-        */
-
-       lf->entries[i].hash = hash;
-       lf->entries[i].filename = talloc_strdup(lf->entries, filename);
-       lf->entries[i].fd = -1;
-
-       lf->entries[i].fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, permissions);
-       if (lf->entries[i].fd < 0) {
-               mode_t dirperm;
-               char *p, *dir;
-
-               /*
-                *      Maybe the directory doesn't exist.  Try to
-                *      create it.
-                */
-               dir = talloc_strdup(lf, filename);
-               if (!dir) goto error;
-               p = strrchr(dir, FR_DIR_SEP);
-               if (!p) {
-                       fr_strerror_printf("No '/' in '%s'", filename);
-                       goto error;
-               }
-               *p = '\0';
-
-               /*
-                *      Ensure that the 'x' bit is set, so that we can
-                *      read the directory.
-                */
-               dirperm = permissions;
-               if ((dirperm & 0600) != 0) dirperm |= 0100;
-               if ((dirperm & 0060) != 0) dirperm |= 0010;
-               if ((dirperm & 0006) != 0) dirperm |= 0001;
-
-               if (rad_mkdir(dir, dirperm) < 0) {
-                       fr_strerror_printf("Failed to create directory %s: %s",
-                                          dir, strerror(errno));
-                       talloc_free(dir);
-                       goto error;
-               }
-               talloc_free(dir);
-
-               lf->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions);
-               if (lf->entries[i].fd < 0) {
-                       fr_strerror_printf("Failed to open file %s: %s",
-                                          filename, strerror(errno));
-                       goto error;
-               } /* else fall through to creating the rest of the entry */
-       } /* else the file was already opened */
-
-do_return:
-       /*
-        *      Lock from the start of the file.
-        */
-       if (lseek(lf->entries[i].fd, 0, SEEK_SET) < 0) {
-               fr_strerror_printf("Failed to seek in file %s: %s",
-                                  filename, strerror(errno));
-
-       error:
-               lf->entries[i].hash = 0;
-               TALLOC_FREE(lf->entries[i].filename);
-               close(lf->entries[i].fd);
-               lf->entries[i].fd = -1;
-
-               PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-               return -1;
-       }
-
-       if (rad_lockfd(lf->entries[i].fd, 0) < 0) {
-               fr_strerror_printf("Failed to lock file %s: %s",
-                                  filename, strerror(errno));
-               goto error;
-       }
-
-       /*
-        *      Maybe someone deleted the file while we were waiting
-        *      for the lock.  If so, re-open it.
-        */
-       if (fstat(lf->entries[i].fd, &st) < 0) {
-               fr_strerror_printf("Failed to stat file %s: %s",
-                                  filename, strerror(errno));
-               goto error;
-       }
-
-       if (st.st_nlink == 0) {
-               close(lf->entries[i].fd);
-               lf->entries[i].fd = open(filename, O_WRONLY | O_CREAT, permissions);
-               if (lf->entries[i].fd < 0) {
-                       fr_strerror_printf("Failed to open file %s: %s",
-                                          filename, strerror(errno));
-                       goto error;
-               }
-       }
-
-       /*
-        *      Seek to the end of the file before returning the FD to
-        *      the caller.
-        */
-       lseek(lf->entries[i].fd, 0, SEEK_END);
-
-       /*
-        *      Return holding the mutex for the entry.
-        */
-       lf->entries[i].last_used = now;
-       lf->entries[i].dup = dup(lf->entries[i].fd);
-       if (lf->entries[i].dup < 0) {
-               fr_strerror_printf("Failed calling dup(): %s",
-                                  strerror(errno));
-               goto error;
-       }
-
-       return lf->entries[i].dup;
-}
-
-/** Close the log file.  Really just return it to the pool.
- *
- * When multithreaded, the FD is locked via a mutex.  This way we're
- * sure that no other thread is writing to the file.  This function
- * will unlock the mutex, so that other threads can write to the file.
- *
- * @param lf The logfile context returned from fr_logfile_init()
- * @param fd the FD to close (i.e. return to the pool)
- * @return 0 on success, or -1 on error
- */
-int fr_logfile_close(fr_logfile_t *lf, int fd)
-{
-       uint32_t i;
-
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) continue;
-
-               /*
-                *      Unlock the bytes that we had previously locked.
-                */
-               if (lf->entries[i].dup == fd) {
-                       (void) rad_unlockfd(lf->entries[i].dup, 0);
-                       close(lf->entries[i].dup); /* releases the fcntl lock */
-                       lf->entries[i].dup = -1;
-
-                       PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-                       return 0;
-               }
-       }
-
-       PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-
-       fr_strerror_printf("Attempt to unlock file which does not exist");
-       return -1;
-}
-
-int fr_logfile_unlock(fr_logfile_t *lf, int fd)
-{
-       uint32_t i;
-
-       for (i = 0; i < lf->max_entries; i++) {
-               if (!lf->entries[i].filename) continue;
-
-               if (lf->entries[i].dup == fd) {
-                       lf->entries[i].dup = -1;
-                       PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-                       return 0;
-               }
-       }
-
-       PTHREAD_MUTEX_UNLOCK(&(lf->mutex));
-
-       fr_strerror_printf("Attempt to unlock file which does not exist");
-       return -1;
-}
index f84f025..aabdf08 100644 (file)
@@ -26,6 +26,7 @@ RCSID("$Id$")
 #include <freeradius-devel/modules.h>
 #include <freeradius-devel/rad_assert.h>
 #include <freeradius-devel/detail.h>
+#include <freeradius-devel/exfile.h>
 
 #include <ctype.h>
 #include <fcntl.h>
@@ -60,7 +61,7 @@ typedef struct detail_instance {
 
        bool            log_srcdst;     //!< Add IP src/dst attributes to entries.
 
-       fr_logfile_t    *lf;            //!< Log file handler
+       exfile_t        *ef;            //!< Log file handler
 
        fr_hash_table_t *ht;            //!< Holds suppressed attributes.
 } detail_instance_t;
@@ -117,8 +118,8 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                inst->name = cf_section_name1(conf);
        }
 
-       inst->lf= fr_logfile_init(inst);
-       if (!inst->lf) {
+       inst->ef = exfile_init(inst, 64, 30);
+       if (!inst->ef) {
                cf_log_err_cs(conf, "Failed creating log file context");
                return -1;
        }
@@ -367,7 +368,7 @@ static rlm_rcode_t CC_HINT(nonnull) detail_do(void *instance, REQUEST *request,
 #endif
 #endif
 
-       outfd = fr_logfile_open(inst->lf, buffer, inst->perm);
+       outfd = exfile_open(inst->ef, buffer, inst->perm);
        if (outfd < 0) {
                RERROR("Couldn't open file %s: %s", buffer, fr_strerror());
                return RLM_MODULE_FAIL;
@@ -398,7 +399,7 @@ skip_group:
                RERROR("Couldn't open file %s: %s", buffer, fr_syserror(errno));
        fail:
                if (outfp) fclose(outfp);
-               fr_logfile_unlock(inst->lf, outfd);
+               exfile_unlock(inst->ef, outfd);
                return RLM_MODULE_FAIL;
        }
 
@@ -408,7 +409,7 @@ skip_group:
         *      Flush everything
         */
        fclose(outfp);
-       fr_logfile_unlock(inst->lf, outfd); /* do NOT close outfp */
+       exfile_unlock(inst->ef, outfd); /* do NOT close outfp */
 
        /*
         *      And everything is fine.
index 6c43b58..81fa9d7 100644 (file)
@@ -26,6 +26,7 @@ RCSID("$Id$")
 #include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/modules.h>
 #include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/exfile.h>
 
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
@@ -59,7 +60,7 @@ typedef struct rlm_linelog_t {
        char const      *group;
        char const      *line;
        char const      *reference;
-       fr_logfile_t    *lf;
+       exfile_t        *ef;
 } rlm_linelog_t;
 
 /*
@@ -119,8 +120,8 @@ static int mod_instantiate(CONF_SECTION *conf, void *instance)
                return -1;
        }
 
-       inst->lf = fr_logfile_init(inst);
-       if (!inst->lf) {
+       inst->ef = exfile_init(inst, 64, 30);
+       if (!inst->ef) {
                cf_log_err_cs(conf, "Failed creating log file context");
                return -1;
        }
@@ -271,7 +272,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_do_linelog(void *instance, REQUEST *requ
                        *p = '/';
                }
 
-               fd = fr_logfile_open(inst->lf, path, inst->permissions);
+               fd = exfile_open(inst->ef, path, inst->permissions);
                if (fd == -1) {
                        ERROR("rlm_linelog: Failed to open %s: %s",
                               path, fr_syserror(errno));
@@ -302,7 +303,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_do_linelog(void *instance, REQUEST *requ
         */
        if (value && (radius_xlat(line, sizeof(line) - 1, request, value, linelog_escape_func, NULL) < 0)) {
                if (fd > -1) {
-                       fr_logfile_close(inst->lf, fd);
+                       exfile_close(inst->ef, fd);
                }
 
                return RLM_MODULE_FAIL;
@@ -313,11 +314,11 @@ static rlm_rcode_t CC_HINT(nonnull) mod_do_linelog(void *instance, REQUEST *requ
 
                if (write(fd, line, strlen(line)) < 0) {
                        ERROR("rlm_linelog: Failed writing: %s", fr_syserror(errno));
-                       fr_logfile_close(inst->lf, fd);
+                       exfile_close(inst->ef, fd);
                        return RLM_MODULE_FAIL;
                }
 
-               fr_logfile_close(inst->lf, fd);
+               exfile_close(inst->ef, fd);
 
 #ifdef HAVE_SYSLOG_H
        } else {
index 2d15e4b..cec91cb 100644 (file)
@@ -31,6 +31,7 @@ RCSID("$Id$")
 #include <freeradius-devel/modules.h>
 #include <freeradius-devel/token.h>
 #include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/exfile.h>
 
 #include <sys/stat.h>
 
@@ -999,8 +1000,8 @@ do { \
                }
        }
 
-       inst->lf = fr_logfile_init(inst);
-       if (!inst->lf) {
+       inst->ef = exfile_init(inst, 64, 30);
+       if (!inst->ef) {
                cf_log_err_cs(conf, "Failed creating log file context");
                return -1;
        }
index d75c27b..7bdf753 100644 (file)
 
 RCSIDH(rlm_sql_h, "$Id$")
 
-#include       <freeradius-devel/radiusd.h>
-#include       <freeradius-devel/connection.h>
-#include       <freeradius-devel/modpriv.h>
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/connection.h>
+#include <freeradius-devel/modpriv.h>
+#include <freeradius-devel/exfile.h>
 
 #define PW_ITEM_CHECK          0
 #define PW_ITEM_REPLY          1
@@ -139,7 +140,7 @@ struct sql_inst {
 
        DICT_ATTR const         *sql_user;      //!< Cached pointer to SQL-User-Name
                                                //!< dictionary attribute.
-       fr_logfile_t            *lf;
+       exfile_t                *ef;
 
        void *handle;
        rlm_sql_module_t *module;
index 94be235..eebf81a 100644 (file)
@@ -494,7 +494,7 @@ void rlm_sql_query_log(rlm_sql_t *inst, REQUEST *request,
                return;
        }
 
-       fd = fr_logfile_open(inst->lf, filename, 0640);
+       fd = exfile_open(inst->ef, filename, 0640);
        if (fd < 0) {
                ERROR("rlm_sql (%s): Couldn't open logfile '%s': %s", inst->config->xlat_name,
                      expanded, fr_syserror(errno));
@@ -514,5 +514,5 @@ void rlm_sql_query_log(rlm_sql_t *inst, REQUEST *request,
        }
 
        talloc_free(expanded);
-       fr_logfile_close(inst->lf, fd);
+       exfile_close(inst->ef, fd);
 }