1*2d543d20SAndroid Build Coastguard Worker #define _GNU_SOURCE
2*2d543d20SAndroid Build Coastguard Worker #include <sys/inotify.h>
3*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
4*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
5*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
6*2d543d20SAndroid Build Coastguard Worker #include <string.h>
7*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
8*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
9*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
10*2d543d20SAndroid Build Coastguard Worker #include <syslog.h>
11*2d543d20SAndroid Build Coastguard Worker #include "restore.h"
12*2d543d20SAndroid Build Coastguard Worker #include <glob.h>
13*2d543d20SAndroid Build Coastguard Worker #include <libgen.h>
14*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
15*2d543d20SAndroid Build Coastguard Worker #include <string.h>
16*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
17*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
18*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
19*2d543d20SAndroid Build Coastguard Worker #include "restorecond.h"
20*2d543d20SAndroid Build Coastguard Worker #include "stringslist.h"
21*2d543d20SAndroid Build Coastguard Worker #include "utmpwatcher.h"
22*2d543d20SAndroid Build Coastguard Worker
23*2d543d20SAndroid Build Coastguard Worker #ifndef GLOB_TILDE
24*2d543d20SAndroid Build Coastguard Worker #define GLOB_TILDE 0
25*2d543d20SAndroid Build Coastguard Worker #endif
26*2d543d20SAndroid Build Coastguard Worker
27*2d543d20SAndroid Build Coastguard Worker #ifndef GLOB_BRACE
28*2d543d20SAndroid Build Coastguard Worker #define GLOB_BRACE 0
29*2d543d20SAndroid Build Coastguard Worker #endif
30*2d543d20SAndroid Build Coastguard Worker
31*2d543d20SAndroid Build Coastguard Worker /* size of the event structure, not counting name */
32*2d543d20SAndroid Build Coastguard Worker #define EVENT_SIZE (sizeof (struct inotify_event))
33*2d543d20SAndroid Build Coastguard Worker /* reasonable guess as to size of 1024 events */
34*2d543d20SAndroid Build Coastguard Worker #define BUF_LEN (1024 * (EVENT_SIZE + 16))
35*2d543d20SAndroid Build Coastguard Worker
36*2d543d20SAndroid Build Coastguard Worker struct watchList {
37*2d543d20SAndroid Build Coastguard Worker struct watchList *next;
38*2d543d20SAndroid Build Coastguard Worker int wd;
39*2d543d20SAndroid Build Coastguard Worker char *dir;
40*2d543d20SAndroid Build Coastguard Worker struct stringsList *files;
41*2d543d20SAndroid Build Coastguard Worker };
42*2d543d20SAndroid Build Coastguard Worker struct watchList *firstDir = NULL;
43*2d543d20SAndroid Build Coastguard Worker
watch_list_isempty(void)44*2d543d20SAndroid Build Coastguard Worker int watch_list_isempty(void) {
45*2d543d20SAndroid Build Coastguard Worker return firstDir == NULL;
46*2d543d20SAndroid Build Coastguard Worker }
47*2d543d20SAndroid Build Coastguard Worker
watch_list_add(int fd,const char * path)48*2d543d20SAndroid Build Coastguard Worker void watch_list_add(int fd, const char *path)
49*2d543d20SAndroid Build Coastguard Worker {
50*2d543d20SAndroid Build Coastguard Worker struct watchList *ptr = NULL;
51*2d543d20SAndroid Build Coastguard Worker size_t i = 0;
52*2d543d20SAndroid Build Coastguard Worker struct watchList *prev = NULL;
53*2d543d20SAndroid Build Coastguard Worker glob_t globbuf;
54*2d543d20SAndroid Build Coastguard Worker char *x = strdup(path);
55*2d543d20SAndroid Build Coastguard Worker if (!x) exitApp("Out of Memory");
56*2d543d20SAndroid Build Coastguard Worker char *file = basename(x);
57*2d543d20SAndroid Build Coastguard Worker char *dir = dirname(x);
58*2d543d20SAndroid Build Coastguard Worker ptr = firstDir;
59*2d543d20SAndroid Build Coastguard Worker int len;
60*2d543d20SAndroid Build Coastguard Worker
61*2d543d20SAndroid Build Coastguard Worker globbuf.gl_offs = 1;
62*2d543d20SAndroid Build Coastguard Worker if (glob(path,
63*2d543d20SAndroid Build Coastguard Worker GLOB_TILDE | GLOB_PERIOD,
64*2d543d20SAndroid Build Coastguard Worker NULL,
65*2d543d20SAndroid Build Coastguard Worker &globbuf) >= 0) {
66*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < globbuf.gl_pathc; i++) {
67*2d543d20SAndroid Build Coastguard Worker len = strlen(globbuf.gl_pathv[i]) - 2;
68*2d543d20SAndroid Build Coastguard Worker if (len > 0 &&
69*2d543d20SAndroid Build Coastguard Worker strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0)
70*2d543d20SAndroid Build Coastguard Worker continue;
71*2d543d20SAndroid Build Coastguard Worker if (len > 0 &&
72*2d543d20SAndroid Build Coastguard Worker strcmp(&globbuf.gl_pathv[i][len], "/..") == 0)
73*2d543d20SAndroid Build Coastguard Worker continue;
74*2d543d20SAndroid Build Coastguard Worker selinux_restorecon(globbuf.gl_pathv[i],
75*2d543d20SAndroid Build Coastguard Worker r_opts.restorecon_flags);
76*2d543d20SAndroid Build Coastguard Worker }
77*2d543d20SAndroid Build Coastguard Worker globfree(&globbuf);
78*2d543d20SAndroid Build Coastguard Worker }
79*2d543d20SAndroid Build Coastguard Worker
80*2d543d20SAndroid Build Coastguard Worker while (ptr != NULL) {
81*2d543d20SAndroid Build Coastguard Worker if (strcmp(dir, ptr->dir) == 0) {
82*2d543d20SAndroid Build Coastguard Worker strings_list_add(&ptr->files, file);
83*2d543d20SAndroid Build Coastguard Worker goto end;
84*2d543d20SAndroid Build Coastguard Worker }
85*2d543d20SAndroid Build Coastguard Worker prev = ptr;
86*2d543d20SAndroid Build Coastguard Worker ptr = ptr->next;
87*2d543d20SAndroid Build Coastguard Worker }
88*2d543d20SAndroid Build Coastguard Worker ptr = calloc(1, sizeof(struct watchList));
89*2d543d20SAndroid Build Coastguard Worker
90*2d543d20SAndroid Build Coastguard Worker if (!ptr) exitApp("Out of Memory");
91*2d543d20SAndroid Build Coastguard Worker
92*2d543d20SAndroid Build Coastguard Worker ptr->wd = inotify_add_watch(fd, dir, IN_CREATE | IN_MOVED_TO);
93*2d543d20SAndroid Build Coastguard Worker if (ptr->wd == -1) {
94*2d543d20SAndroid Build Coastguard Worker free(ptr);
95*2d543d20SAndroid Build Coastguard Worker if (! run_as_user)
96*2d543d20SAndroid Build Coastguard Worker syslog(LOG_ERR, "Unable to watch (%s) %s\n",
97*2d543d20SAndroid Build Coastguard Worker path, strerror(errno));
98*2d543d20SAndroid Build Coastguard Worker goto end;
99*2d543d20SAndroid Build Coastguard Worker }
100*2d543d20SAndroid Build Coastguard Worker
101*2d543d20SAndroid Build Coastguard Worker ptr->dir = strdup(dir);
102*2d543d20SAndroid Build Coastguard Worker if (!ptr->dir)
103*2d543d20SAndroid Build Coastguard Worker exitApp("Out of Memory");
104*2d543d20SAndroid Build Coastguard Worker
105*2d543d20SAndroid Build Coastguard Worker strings_list_add(&ptr->files, file);
106*2d543d20SAndroid Build Coastguard Worker if (prev)
107*2d543d20SAndroid Build Coastguard Worker prev->next = ptr;
108*2d543d20SAndroid Build Coastguard Worker else
109*2d543d20SAndroid Build Coastguard Worker firstDir = ptr;
110*2d543d20SAndroid Build Coastguard Worker
111*2d543d20SAndroid Build Coastguard Worker if (debug_mode)
112*2d543d20SAndroid Build Coastguard Worker printf("%d: Dir=%s, File=%s\n", ptr->wd, ptr->dir, file);
113*2d543d20SAndroid Build Coastguard Worker
114*2d543d20SAndroid Build Coastguard Worker end:
115*2d543d20SAndroid Build Coastguard Worker free(x);
116*2d543d20SAndroid Build Coastguard Worker return;
117*2d543d20SAndroid Build Coastguard Worker }
118*2d543d20SAndroid Build Coastguard Worker
119*2d543d20SAndroid Build Coastguard Worker /*
120*2d543d20SAndroid Build Coastguard Worker A file was in a direcroty has been created. This function checks to
121*2d543d20SAndroid Build Coastguard Worker see if it is one that we are watching.
122*2d543d20SAndroid Build Coastguard Worker */
123*2d543d20SAndroid Build Coastguard Worker
watch_list_find(int wd,const char * file)124*2d543d20SAndroid Build Coastguard Worker int watch_list_find(int wd, const char *file)
125*2d543d20SAndroid Build Coastguard Worker {
126*2d543d20SAndroid Build Coastguard Worker struct watchList *ptr = NULL;
127*2d543d20SAndroid Build Coastguard Worker
128*2d543d20SAndroid Build Coastguard Worker ptr = firstDir;
129*2d543d20SAndroid Build Coastguard Worker
130*2d543d20SAndroid Build Coastguard Worker if (debug_mode)
131*2d543d20SAndroid Build Coastguard Worker printf("%d: File=%s\n", wd, file);
132*2d543d20SAndroid Build Coastguard Worker while (ptr != NULL) {
133*2d543d20SAndroid Build Coastguard Worker if (ptr->wd == wd) {
134*2d543d20SAndroid Build Coastguard Worker int exact=0;
135*2d543d20SAndroid Build Coastguard Worker if (strings_list_find(ptr->files, file, &exact) == 0) {
136*2d543d20SAndroid Build Coastguard Worker char *path = NULL;
137*2d543d20SAndroid Build Coastguard Worker if (asprintf(&path, "%s/%s", ptr->dir, file) <
138*2d543d20SAndroid Build Coastguard Worker 0)
139*2d543d20SAndroid Build Coastguard Worker exitApp("Error allocating memory.");
140*2d543d20SAndroid Build Coastguard Worker
141*2d543d20SAndroid Build Coastguard Worker selinux_restorecon(path,
142*2d543d20SAndroid Build Coastguard Worker r_opts.restorecon_flags);
143*2d543d20SAndroid Build Coastguard Worker free(path);
144*2d543d20SAndroid Build Coastguard Worker return 0;
145*2d543d20SAndroid Build Coastguard Worker }
146*2d543d20SAndroid Build Coastguard Worker if (debug_mode)
147*2d543d20SAndroid Build Coastguard Worker strings_list_print(ptr->files);
148*2d543d20SAndroid Build Coastguard Worker
149*2d543d20SAndroid Build Coastguard Worker /* Not found in this directory */
150*2d543d20SAndroid Build Coastguard Worker return -1;
151*2d543d20SAndroid Build Coastguard Worker }
152*2d543d20SAndroid Build Coastguard Worker ptr = ptr->next;
153*2d543d20SAndroid Build Coastguard Worker }
154*2d543d20SAndroid Build Coastguard Worker /* Did not find a directory */
155*2d543d20SAndroid Build Coastguard Worker return -1;
156*2d543d20SAndroid Build Coastguard Worker }
157*2d543d20SAndroid Build Coastguard Worker
watch_list_free(int fd)158*2d543d20SAndroid Build Coastguard Worker void watch_list_free(int fd)
159*2d543d20SAndroid Build Coastguard Worker {
160*2d543d20SAndroid Build Coastguard Worker struct watchList *ptr = NULL;
161*2d543d20SAndroid Build Coastguard Worker struct watchList *prev = NULL;
162*2d543d20SAndroid Build Coastguard Worker ptr = firstDir;
163*2d543d20SAndroid Build Coastguard Worker
164*2d543d20SAndroid Build Coastguard Worker while (ptr != NULL) {
165*2d543d20SAndroid Build Coastguard Worker inotify_rm_watch(fd, ptr->wd);
166*2d543d20SAndroid Build Coastguard Worker strings_list_free(ptr->files);
167*2d543d20SAndroid Build Coastguard Worker free(ptr->dir);
168*2d543d20SAndroid Build Coastguard Worker prev = ptr;
169*2d543d20SAndroid Build Coastguard Worker ptr = ptr->next;
170*2d543d20SAndroid Build Coastguard Worker free(prev);
171*2d543d20SAndroid Build Coastguard Worker }
172*2d543d20SAndroid Build Coastguard Worker firstDir = NULL;
173*2d543d20SAndroid Build Coastguard Worker }
174*2d543d20SAndroid Build Coastguard Worker
175*2d543d20SAndroid Build Coastguard Worker /*
176*2d543d20SAndroid Build Coastguard Worker Inotify watch loop
177*2d543d20SAndroid Build Coastguard Worker */
watch(int fd,const char * watch_file)178*2d543d20SAndroid Build Coastguard Worker int watch(int fd, const char *watch_file)
179*2d543d20SAndroid Build Coastguard Worker {
180*2d543d20SAndroid Build Coastguard Worker char buf[BUF_LEN];
181*2d543d20SAndroid Build Coastguard Worker int len, i = 0;
182*2d543d20SAndroid Build Coastguard Worker if (firstDir == NULL) return 0;
183*2d543d20SAndroid Build Coastguard Worker
184*2d543d20SAndroid Build Coastguard Worker len = read(fd, buf, BUF_LEN);
185*2d543d20SAndroid Build Coastguard Worker if (len < 0) {
186*2d543d20SAndroid Build Coastguard Worker if (terminate == 0) {
187*2d543d20SAndroid Build Coastguard Worker syslog(LOG_ERR, "Read error (%s)", strerror(errno));
188*2d543d20SAndroid Build Coastguard Worker return 0;
189*2d543d20SAndroid Build Coastguard Worker }
190*2d543d20SAndroid Build Coastguard Worker syslog(LOG_INFO, "terminated");
191*2d543d20SAndroid Build Coastguard Worker return -1;
192*2d543d20SAndroid Build Coastguard Worker } else if (!len)
193*2d543d20SAndroid Build Coastguard Worker /* BUF_LEN too small? */
194*2d543d20SAndroid Build Coastguard Worker return -1;
195*2d543d20SAndroid Build Coastguard Worker while (i < len) {
196*2d543d20SAndroid Build Coastguard Worker struct inotify_event *event;
197*2d543d20SAndroid Build Coastguard Worker event = (struct inotify_event *)&buf[i];
198*2d543d20SAndroid Build Coastguard Worker if (debug_mode)
199*2d543d20SAndroid Build Coastguard Worker printf("wd=%d mask=%u cookie=%u len=%u\n",
200*2d543d20SAndroid Build Coastguard Worker event->wd, event->mask,
201*2d543d20SAndroid Build Coastguard Worker event->cookie, event->len);
202*2d543d20SAndroid Build Coastguard Worker if (event->mask & ~IN_IGNORED) {
203*2d543d20SAndroid Build Coastguard Worker if (event->wd == master_wd)
204*2d543d20SAndroid Build Coastguard Worker read_config(fd, watch_file);
205*2d543d20SAndroid Build Coastguard Worker else {
206*2d543d20SAndroid Build Coastguard Worker switch (utmpwatcher_handle(fd, event->wd)) {
207*2d543d20SAndroid Build Coastguard Worker case -1: /* Message was not for utmpwatcher */
208*2d543d20SAndroid Build Coastguard Worker if (event->len)
209*2d543d20SAndroid Build Coastguard Worker watch_list_find(event->wd, event->name);
210*2d543d20SAndroid Build Coastguard Worker break;
211*2d543d20SAndroid Build Coastguard Worker case 1: /* utmp has changed need to reload */
212*2d543d20SAndroid Build Coastguard Worker read_config(fd, watch_file);
213*2d543d20SAndroid Build Coastguard Worker break;
214*2d543d20SAndroid Build Coastguard Worker
215*2d543d20SAndroid Build Coastguard Worker default: /* No users logged in or out */
216*2d543d20SAndroid Build Coastguard Worker break;
217*2d543d20SAndroid Build Coastguard Worker }
218*2d543d20SAndroid Build Coastguard Worker }
219*2d543d20SAndroid Build Coastguard Worker }
220*2d543d20SAndroid Build Coastguard Worker
221*2d543d20SAndroid Build Coastguard Worker i += EVENT_SIZE + event->len;
222*2d543d20SAndroid Build Coastguard Worker }
223*2d543d20SAndroid Build Coastguard Worker return 0;
224*2d543d20SAndroid Build Coastguard Worker }
225*2d543d20SAndroid Build Coastguard Worker
process_config(int fd,FILE * cfg)226*2d543d20SAndroid Build Coastguard Worker static void process_config(int fd, FILE * cfg)
227*2d543d20SAndroid Build Coastguard Worker {
228*2d543d20SAndroid Build Coastguard Worker char *line_buf = NULL;
229*2d543d20SAndroid Build Coastguard Worker size_t len = 0;
230*2d543d20SAndroid Build Coastguard Worker
231*2d543d20SAndroid Build Coastguard Worker while (getline(&line_buf, &len, cfg) > 0) {
232*2d543d20SAndroid Build Coastguard Worker char *buffer = line_buf;
233*2d543d20SAndroid Build Coastguard Worker while (isspace(*buffer))
234*2d543d20SAndroid Build Coastguard Worker buffer++;
235*2d543d20SAndroid Build Coastguard Worker if (buffer[0] == '#')
236*2d543d20SAndroid Build Coastguard Worker continue;
237*2d543d20SAndroid Build Coastguard Worker int l = strlen(buffer) - 1;
238*2d543d20SAndroid Build Coastguard Worker if (l <= 0)
239*2d543d20SAndroid Build Coastguard Worker continue;
240*2d543d20SAndroid Build Coastguard Worker buffer[l] = 0;
241*2d543d20SAndroid Build Coastguard Worker if (buffer[0] == '~') {
242*2d543d20SAndroid Build Coastguard Worker if (run_as_user) {
243*2d543d20SAndroid Build Coastguard Worker char *ptr=NULL;
244*2d543d20SAndroid Build Coastguard Worker if (asprintf(&ptr, "%s%s", homedir, &buffer[1]) < 0)
245*2d543d20SAndroid Build Coastguard Worker exitApp("Error allocating memory.");
246*2d543d20SAndroid Build Coastguard Worker
247*2d543d20SAndroid Build Coastguard Worker watch_list_add(fd, ptr);
248*2d543d20SAndroid Build Coastguard Worker free(ptr);
249*2d543d20SAndroid Build Coastguard Worker } else {
250*2d543d20SAndroid Build Coastguard Worker utmpwatcher_add(fd, &buffer[1]);
251*2d543d20SAndroid Build Coastguard Worker }
252*2d543d20SAndroid Build Coastguard Worker } else {
253*2d543d20SAndroid Build Coastguard Worker watch_list_add(fd, buffer);
254*2d543d20SAndroid Build Coastguard Worker }
255*2d543d20SAndroid Build Coastguard Worker }
256*2d543d20SAndroid Build Coastguard Worker free(line_buf);
257*2d543d20SAndroid Build Coastguard Worker }
258*2d543d20SAndroid Build Coastguard Worker
259*2d543d20SAndroid Build Coastguard Worker /*
260*2d543d20SAndroid Build Coastguard Worker Read config file ignoring Comment lines
261*2d543d20SAndroid Build Coastguard Worker Files specified one per line. Files with "~" will be expanded to the logged in users
262*2d543d20SAndroid Build Coastguard Worker homedirs.
263*2d543d20SAndroid Build Coastguard Worker */
264*2d543d20SAndroid Build Coastguard Worker
read_config(int fd,const char * watch_file_path)265*2d543d20SAndroid Build Coastguard Worker void read_config(int fd, const char *watch_file_path)
266*2d543d20SAndroid Build Coastguard Worker {
267*2d543d20SAndroid Build Coastguard Worker
268*2d543d20SAndroid Build Coastguard Worker FILE *cfg = NULL;
269*2d543d20SAndroid Build Coastguard Worker if (debug_mode)
270*2d543d20SAndroid Build Coastguard Worker printf("Read Config\n");
271*2d543d20SAndroid Build Coastguard Worker
272*2d543d20SAndroid Build Coastguard Worker watch_list_free(fd);
273*2d543d20SAndroid Build Coastguard Worker
274*2d543d20SAndroid Build Coastguard Worker cfg = fopen(watch_file_path, "r");
275*2d543d20SAndroid Build Coastguard Worker if (!cfg){
276*2d543d20SAndroid Build Coastguard Worker perror(watch_file_path);
277*2d543d20SAndroid Build Coastguard Worker exitApp("Error reading config file");
278*2d543d20SAndroid Build Coastguard Worker }
279*2d543d20SAndroid Build Coastguard Worker process_config(fd, cfg);
280*2d543d20SAndroid Build Coastguard Worker fclose(cfg);
281*2d543d20SAndroid Build Coastguard Worker
282*2d543d20SAndroid Build Coastguard Worker inotify_rm_watch(fd, master_wd);
283*2d543d20SAndroid Build Coastguard Worker master_wd =
284*2d543d20SAndroid Build Coastguard Worker inotify_add_watch(fd, watch_file_path, IN_MOVED_FROM | IN_MODIFY);
285*2d543d20SAndroid Build Coastguard Worker if (master_wd == -1)
286*2d543d20SAndroid Build Coastguard Worker exitApp("Error watching config file.");
287*2d543d20SAndroid Build Coastguard Worker }
288