+/* -*-c-*-
+ *
+ * $Id: fwatch.c,v 1.1 2001/02/03 18:43:56 mdw Exp $
+ *
+ * Watch a file for changes
+ *
+ * (c) 2001 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * mLib 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with mLib; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: fwatch.c,v $
+ * Revision 1.1 2001/02/03 18:43:56 mdw
+ * New feature: watch a file for changes.
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "fwatch.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @doupdate@ --- *
+ *
+ * Arguments: @fwatch *f@ = pointer to an @fwatch@ structure
+ * @struct stat *st@ = pointer to file state
+ * @int err@ = whether there was an error
+ *
+ * Returns: Nonzero if the file has changed.
+ *
+ * Use: Updates the information in an @fwatch@ block.
+ */
+
+static void copy(fwatch *f, struct stat *st)
+{
+ f->dev = st->st_dev; f->ino = st->st_ino;
+ f->mtime = st->st_mtime; f->size = st->st_size;
+ f->mode = st->st_mode;
+ f->uid = st->st_uid; f->gid = st->st_gid;
+}
+
+static int doupdate(fwatch *f, struct stat *st, int err)
+{
+ /* --- Fiddle with the error state --- *
+ *
+ * Only the presence or absence of error is interesting to someone wanting
+ * to read the file.
+ */
+
+ if (err)
+ err = errno;
+ if (err || f->err) {
+ if (!err != !f->err) {
+ f->err = err;
+ if (!err)
+ copy(f, st);
+ return (1);
+ }
+ return (0);
+ }
+
+ /* --- Check everything else --- */
+
+ if (st->st_dev != f->dev || st->st_ino != f->ino ||
+ st->st_mtime != f->mtime || st->st_size != f->size ||
+ st->st_mode != f->mode ||
+ st->st_uid != f->uid || st->st_gid != f->gid) {
+ copy(f, st);
+ return (1);
+ }
+ return (0);
+}
+
+/* --- @fwatch_init@, @fwatch_update@, etc --- *
+ *
+ * Arguments: @fwatch *f@ = pointer to an @fwatch@ structure
+ * @const char *name@ = name of the file to watch
+ * @int fd@ = a file descriptor to watch
+ *
+ * Returns: The @update@ functions return nonzero if the file has
+ * changed.
+ *
+ * Use: Stores information about a file which can be used to watch
+ * for changes. The structures may be freed without telling
+ * anyone.
+ */
+
+void fwatch_init(fwatch *f, const char *name)
+{
+ struct stat st;
+ memset(f, 0, sizeof(*f));
+ doupdate(f, &st, stat(name, &st));
+}
+
+void fwatch_initfd(fwatch *f, int fd)
+{
+ struct stat st;
+ memset(f, 0, sizeof(*f));
+ doupdate(f, &st, fstat(fd, &st));
+}
+
+int fwatch_update(fwatch *f, const char *name)
+{
+ struct stat st;
+ return (doupdate(f, &st, stat(name, &st)));
+}
+
+int fwatch_updatefd(fwatch *f, int fd)
+{
+ struct stat st;
+ return (doupdate(f, &st, fstat(fd, &st)));
+}
+
+/*----- That's all, folks -------------------------------------------------*/