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