chiark / gitweb /
New feature: watch a file for changes.
[mLib] / fwatch.c
CommitLineData
32e1147e 1/* -*-c-*-
2 *
3 * $Id: fwatch.c,v 1.1 2001/02/03 18:43:56 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/*----- Revision history --------------------------------------------------*
31 *
32 * $Log: fwatch.c,v $
33 * Revision 1.1 2001/02/03 18:43:56 mdw
34 * New feature: watch a file for changes.
35 *
36 */
37
38/*----- Header files ------------------------------------------------------*/
39
40#include <errno.h>
41
42#include <sys/types.h>
43#include <sys/stat.h>
44
45#include "fwatch.h"
46
47/*----- Main code ---------------------------------------------------------*/
48
49/* --- @doupdate@ --- *
50 *
51 * Arguments: @fwatch *f@ = pointer to an @fwatch@ structure
52 * @struct stat *st@ = pointer to file state
53 * @int err@ = whether there was an error
54 *
55 * Returns: Nonzero if the file has changed.
56 *
57 * Use: Updates the information in an @fwatch@ block.
58 */
59
60static void copy(fwatch *f, struct stat *st)
61{
62 f->dev = st->st_dev; f->ino = st->st_ino;
63 f->mtime = st->st_mtime; f->size = st->st_size;
64 f->mode = st->st_mode;
65 f->uid = st->st_uid; f->gid = st->st_gid;
66}
67
68static int doupdate(fwatch *f, struct stat *st, int err)
69{
70 /* --- Fiddle with the error state --- *
71 *
72 * Only the presence or absence of error is interesting to someone wanting
73 * to read the file.
74 */
75
76 if (err)
77 err = errno;
78 if (err || f->err) {
79 if (!err != !f->err) {
80 f->err = err;
81 if (!err)
82 copy(f, st);
83 return (1);
84 }
85 return (0);
86 }
87
88 /* --- Check everything else --- */
89
90 if (st->st_dev != f->dev || st->st_ino != f->ino ||
91 st->st_mtime != f->mtime || st->st_size != f->size ||
92 st->st_mode != f->mode ||
93 st->st_uid != f->uid || st->st_gid != f->gid) {
94 copy(f, st);
95 return (1);
96 }
97 return (0);
98}
99
100/* --- @fwatch_init@, @fwatch_update@, etc --- *
101 *
102 * Arguments: @fwatch *f@ = pointer to an @fwatch@ structure
103 * @const char *name@ = name of the file to watch
104 * @int fd@ = a file descriptor to watch
105 *
106 * Returns: The @update@ functions return nonzero if the file has
107 * changed.
108 *
109 * Use: Stores information about a file which can be used to watch
110 * for changes. The structures may be freed without telling
111 * anyone.
112 */
113
114void fwatch_init(fwatch *f, const char *name)
115{
116 struct stat st;
117 memset(f, 0, sizeof(*f));
118 doupdate(f, &st, stat(name, &st));
119}
120
121void fwatch_initfd(fwatch *f, int fd)
122{
123 struct stat st;
124 memset(f, 0, sizeof(*f));
125 doupdate(f, &st, fstat(fd, &st));
126}
127
128int fwatch_update(fwatch *f, const char *name)
129{
130 struct stat st;
131 return (doupdate(f, &st, stat(name, &st)));
132}
133
134int fwatch_updatefd(fwatch *f, int fd)
135{
136 struct stat st;
137 return (doupdate(f, &st, fstat(fd, &st)));
138}
139
140/*----- That's all, folks -------------------------------------------------*/