From 32e1147e2e732907833db7fd16026cf203247141 Mon Sep 17 00:00:00 2001 Message-Id: <32e1147e2e732907833db7fd16026cf203247141.1714898855.git.mdw@distorted.org.uk> From: Mark Wooding Date: Sat, 3 Feb 2001 18:43:59 +0000 Subject: [PATCH] New feature: watch a file for changes. Organization: Straylight/Edgeware From: mdw --- Makefile.am | 9 ++-- fwatch.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++ fwatch.h | 90 +++++++++++++++++++++++++++++++ man/.cvsignore | 4 ++ man/fwatch.3 | 41 +++++++++++++++ man/mLib.3 | 6 +++ 6 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 fwatch.c create mode 100644 fwatch.h create mode 100644 man/fwatch.3 diff --git a/Makefile.am b/Makefile.am index e5f3753..ded3be5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ## -*-Makefile-*- ## -## $Id: Makefile.am,v 1.30 2001/01/25 21:11:41 mdw Exp $ +## $Id: Makefile.am,v 1.31 2001/02/03 18:43:56 mdw Exp $ ## ## Building the distribution ## @@ -29,6 +29,9 @@ ##----- Revision history ---------------------------------------------------- ## ## $Log: Makefile.am,v $ +## Revision 1.31 2001/02/03 18:43:56 mdw +## New feature: watch a file for changes. +## ## Revision 1.30 2001/01/25 21:11:41 mdw ## Use `$(MAKE)' in the `install-man' rule, so that the jobserver doesn't ## whinge. @@ -118,7 +121,7 @@ pkginclude_HEADERS = \ alloc.h arena.h bits.h exc.h quis.h report.h sub.h trace.h track.h \ pool.h \ atom.h assoc.h darray.h dstr.h dspool.h hash.h sym.h crc32.h \ - env.h fdflags.h lock.h \ + env.h fdflags.h fwatch.h lock.h \ bres.h conn.h lbuf.h ident.h pkbuf.h sel.h selbuf.h selpk.h sig.h \ tv.h \ base64.h mdwopt.h str.h testrig.h url.h @@ -135,7 +138,7 @@ libmLib_la_SOURCES = \ pool.c pool-file.c pool-sub.c \ atom.c assoc.c darray.c dstr.c dputf.c dspool.c hash.c sym.c \ crc32.c crc32-tab.c \ - env.c fdflags.c lock.c \ + env.c fdflags.c fwatch.c lock.c \ bres.c conn.c lbuf.c ident.c pkbuf.c sel.c selbuf.c selpk.c sig.c \ tv.c \ base64.c mdwopt.c str.c testrig.c url.c diff --git a/fwatch.c b/fwatch.c new file mode 100644 index 0000000..ecf945a --- /dev/null +++ b/fwatch.c @@ -0,0 +1,140 @@ +/* -*-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 + +#include +#include + +#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 -------------------------------------------------*/ diff --git a/fwatch.h b/fwatch.h new file mode 100644 index 0000000..1a0898a --- /dev/null +++ b/fwatch.h @@ -0,0 +1,90 @@ +/* -*-c-*- + * + * $Id: fwatch.h,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.h,v $ + * Revision 1.1 2001/02/03 18:43:56 mdw + * New feature: watch a file for changes. + * + */ + +#ifndef MLIB_FWATCH_H +#define MLIB_FWATCH_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct fwatch { + int err; + dev_t dev; + ino_t ino; + time_t mtime; + off_t size; + mode_t mode; + uid_t uid; + gid_t gid; +} fwatch; + +/*----- Functions provided ------------------------------------------------*/ + +/* --- @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. + */ + +extern void fwatch_init(fwatch */*f*/, const char */*name*/); +extern void fwatch_initfd(fwatch */*f*/, int /*fd*/); +extern int fwatch_update(fwatch */*f*/, const char */*name*/); +extern int fwatch_updatefd(fwatch */*f*/, int /*fd*/); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/man/.cvsignore b/man/.cvsignore index 6b9f144..f80f4ab 100644 --- a/man/.cvsignore +++ b/man/.cvsignore @@ -169,6 +169,10 @@ env_get.3 env_import.3 env_put.3 exc_uncaught.3 +fwatch_init.3 +fwatch_initfd.3 +fwatch_update.3 +fwatch_updatefd.3 hash_bin.3 hash_create.3 hash_destroy.3 diff --git a/man/fwatch.3 b/man/fwatch.3 new file mode 100644 index 0000000..a22e031 --- /dev/null +++ b/man/fwatch.3 @@ -0,0 +1,41 @@ +.\" -*-nroff-*- +.TH fwatch 3 "3 February 2001" mLib +.SH NAME +fwatch \- watch a file for changes +.\" @fwatch_init +.\" @fwatch_initfd +.\" @fwatch_update +.\" @fwatch_updatefd +.SH SYNOPSIS +.nf +.B "#include " + +.BI "void fwatch_init(fwatch *" f ", const char *" name ); +.BI "void fwatch_initfd(fwatch *" f ", int " fd ); +.BI "int fwatch_update(fwatch *" f ", const char *" name ); +.BI "int fwatch_updatefd(fwatch *" f ", int " fd ); +.fi +.SH DESCRIPTION +These functions watch a file for changes. Use +.B fwatch_init +or +.B fwatch_initfd +to initialize a +.B fwatch +block with information about a file; then later, the functions +.B fwatch_update +and +.B fwatch_updatefd +will update the information in the structure and inform you whether the +file changed. +.PP +The +.B fwatch +functions can't return errors: they remember errors as part of the file +state instead. The +.B update +functions return zero if the file has not changed or nonzero if it has. +.SH SEE ALSO +.BR mLib (3). +.SH AUTHOR +Mark Wooding, diff --git a/man/mLib.3 b/man/mLib.3 index f109d19..0796883 100644 --- a/man/mLib.3 +++ b/man/mLib.3 @@ -167,6 +167,11 @@ The module manipulates file descriptor flags in a fairly painless way. .PP The +.BR fwatch (3) +module allows you to easily find out whether a file has changed since +the last time you looked at it. +.PP +The .BR lbuf (3) module implements a `line buffer', which is an object that emits completed lines of text from an incoming asynchronous data stream. It's @@ -261,6 +266,7 @@ module does background hostname and address resolution. .BR env (3), .BR exc (3), .BR fdflags (3), +.BR fwatch (3), .BR hash (3), .BR ident (3), .BR lbuf (3), -- [mdw]