chiark / gitweb /
69f5498a411ed1f0a0f78fd4f3be1deed894a8dd
[mLib] / fwatch.c
1 /* -*-c-*-
2  *
3  * Watch a file for changes
4  *
5  * (c) 2001 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
12  * mLib is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * mLib is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with mLib; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <errno.h>
31 #include <string.h>
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35
36 #include "fwatch.h"
37
38 /*----- Main code ---------------------------------------------------------*/
39
40 /* --- @doupdate@ --- *
41  *
42  * Arguments:   @fwatch *f@ = pointer to an @fwatch@ structure
43  *              @struct stat *st@ = pointer to file state
44  *              @int err@ = whether there was an error
45  *
46  * Returns:     Nonzero if the file has changed.
47  *
48  * Use:         Updates the information in an @fwatch@ block.
49  */
50
51 static void copy(fwatch *f, struct stat *st)
52 {
53   f->dev = st->st_dev; f->ino = st->st_ino;
54   f->mtime = st->st_mtime; f->size = st->st_size;
55   f->mode = st->st_mode;
56   f->uid = st->st_uid; f->gid = st->st_gid;
57 }
58
59 static int doupdate(fwatch *f, struct stat *st, int err)
60 {
61   /* --- Fiddle with the error state --- *
62    *
63    * Only the presence or absence of error is interesting to someone wanting
64    * to read the file.
65    */
66
67   if (err)
68     err = errno;
69   if (err || f->err) {
70     if (!err != !f->err) {
71       f->err = err;
72       if (!err)
73         copy(f, st);
74       return (1);
75     }
76     return (0);
77   }
78
79   /* --- Check everything else --- */
80
81   if (st->st_dev != f->dev || st->st_ino != f->ino ||
82       st->st_mtime != f->mtime || st->st_size != f->size ||
83       st->st_mode != f->mode ||
84       st->st_uid != f->uid || st->st_gid != f->gid) {
85     copy(f, st);
86     return (1);
87   }
88   return (0);
89 }
90
91 /* --- @fwatch_init@, @fwatch_update@, etc --- *
92  *
93  * Arguments:   @fwatch *f@ = pointer to an @fwatch@ structure
94  *              @const char *name@ = name of the file to watch
95  *              @int fd@ = a file descriptor to watch
96  *
97  * Returns:     The @update@ functions return nonzero if the file has
98  *              changed.
99  *
100  * Use:         Stores information about a file which can be used to watch
101  *              for changes.  The structures may be freed without telling
102  *              anyone.
103  */
104
105 void fwatch_init(fwatch *f, const char *name)
106 {
107   struct stat st;
108   memset(f, 0, sizeof(*f));
109   doupdate(f, &st, stat(name, &st));
110 }
111
112 void fwatch_initfd(fwatch *f, int fd)
113 {
114   struct stat st;
115   memset(f, 0, sizeof(*f));
116   doupdate(f, &st, fstat(fd, &st));
117 }
118
119 int fwatch_update(fwatch *f, const char *name)
120 {
121   struct stat st;
122   return (doupdate(f, &st, stat(name, &st)));
123 }
124
125 int fwatch_updatefd(fwatch *f, int fd)
126 {
127   struct stat st;
128   return (doupdate(f, &st, fstat(fd, &st)));
129 }
130
131 /*----- That's all, folks -------------------------------------------------*/