Annotation of fam/fam/IMonLinux.c++, Revision 1.1.1.1
1.1 trev 1: // Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved.
2: //
3: // This program is free software; you can redistribute it and/or modify it
4: // under the terms of version 2 of the GNU General Public License as
5: // published by the Free Software Foundation.
6: //
7: // This program is distributed in the hope that it would be useful, but
8: // WITHOUT ANY WARRANTY; without even the implied warranty of
9: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
10: // license provided herein, whether implied or otherwise, is limited to
11: // this program in accordance with the express provisions of the GNU
12: // General Public License. Patent licenses, if any, provided herein do not
13: // apply to combinations of this program with other product or programs, or
14: // any other product whatsoever. This program is distributed without any
15: // warranty that the program is delivered free of the rightful claim of any
16: // third person by way of infringement or the like. See the GNU General
17: // Public License for more details.
18: //
19: // You should have received a copy of the GNU General Public License along
20: // with this program; if not, write the Free Software Foundation, Inc., 59
21: // Temple Place - Suite 330, Boston MA 02111-1307, USA.
22:
23: #include "IMon.h"
24: #include "Log.h"
25:
26: #include <stdio.h>
27: #include <unistd.h>
28: #include <fcntl.h>
29: #include <stdlib.h>
30: #include <string.h>
31:
32: #include <sys/types.h>
33: #include <sys/wait.h>
34:
35: #include <sys/ioctl.h>
36: #include <sys/sysmacros.h>
37: #include <linux/imon.h>
38:
39: #define DEV_IMON "/dev/imon"
40: const intmask_t INTEREST_MASK = (IMON_CONTENT | IMON_ATTRIBUTE | IMON_DELETE |
41: IMON_EXEC | IMON_EXIT);
42:
43: enum OpenStatus { OPEN_OK, OPEN_RETRY, OPEN_FAILED };
44:
45: static OpenStatus open_device(int& imonfd)
46: {
47: int major;
48: bool foundMajor = false;
49: char line[100], name[100];
50:
51: FILE* dev = fopen("/proc/devices", "r");
52: if (!dev) {
53: Log::critical("can't open /proc/devices: %m");
54: return OPEN_FAILED;
55: }
56: while (fgets(line, sizeof line, dev) != NULL) {
57: if (sscanf(line, "%d %s\n", &major, name) == 2
58: && strcmp(name, "imon") == 0) {
59: foundMajor = true;
60: break;
61: }
62: }
63: fclose(dev);
64:
65: if (!foundMajor) {
66: return OPEN_RETRY;
67: }
68:
69: (void)unlink(DEV_IMON);
70: if (mknod(DEV_IMON, S_IFCHR | 0600, makedev(major, 0)) == -1) {
71: Log::critical("can't create %s: %m", DEV_IMON);
72: return OPEN_FAILED;
73: }
74:
75: int imon = open(DEV_IMON, O_RDONLY | O_NONBLOCK);
76: (void)unlink(DEV_IMON);
77: if (imon == -1) {
78: Log::critical("can't open %s: %m", DEV_IMON);
79: return OPEN_FAILED;
80: }
81: imonfd = imon;
82: return OPEN_OK;
83: }
84:
85: static void insmod()
86: {
87: pid_t pid = fork();
88: if (pid == 0) {
89: execl("/sbin/insmod", "insmod", "imon", NULL);
90: exit(1);
91: }
92: if (pid > 0) {
93: waitpid(pid, NULL, 0);
94: }
95: }
96:
97: int IMon::imon_open()
98: {
99: int imon;
100: OpenStatus status = open_device(imon);
101: if (status == OPEN_RETRY) {
102: insmod();
103: status = open_device(imon);
104: }
105: if (status == OPEN_RETRY) {
106: Log::critical("can't open %s: imon major number not found in /proc/devices", DEV_IMON);
107: return -1;
108: }
109: if (status != OPEN_OK) {
110: Log::critical("can't open %s: %m", DEV_IMON);
111: return -1;
112: }
113: return imon;
114: }
115:
116: IMon::Status IMon::imon_express(const char *name, struct stat *status)
117: {
118: famstat_t famstat;
119: struct interest interest = { name, &famstat, INTEREST_MASK };
120: int rc = ioctl(imonfd, IMONIOC_EXPRESS, &interest);
121: if (rc < 0)
122: {
123: if (name[0] == '/') {
124: Log::info("IMONIOC_EXPRESS on \"%s\" failed (euid: %i): %m",
125: name, geteuid());
126: } else {
127: char * cwd = getcwd(0, 256);
128: Log::info("IMONIOC_EXPRESS on \"%s\" with cwd \"%s\" failed (euid: %i): %m",
129: name,cwd,geteuid());
130: free(cwd);
131: }
132: return BAD;
133: }
134:
135: //
136: // Check for a race condition; if someone removed or changed the
137: // file at the same time that we are expressing interest in it,
138: // revoke the interest so we don't get notifications about changes
139: // to a recycled inode that we don't otherwise care about.
140: //
141: struct stat st;
142: if (status == NULL) {
143: status = &st;
144: }
145: if (stat(name, status) == -1) {
146: Log::perror("stat on \"%s\" failed", name);
147: revoke(name, famstat.st_dev, famstat.st_ino);
148: return BAD;
149: }
150: if (status->st_dev != famstat.st_dev
151: || status->st_ino != famstat.st_ino) {
152: Log::error("File \"%s\" changed between express and stat",
153: name);
154: revoke(name, famstat.st_dev, famstat.st_ino);
155: return BAD;
156: }
157:
158: Log::debug("told imon to monitor \"%s\" = dev %d/%d, ino %d", name,
159: major(status->st_dev), minor(status->st_dev),
160: status->st_ino);
161:
162: return OK;
163: }
164:
165: IMon::Status IMon::imon_revoke(const char *name, dev_t dev, ino_t ino)
166: {
167: revoke_t rv = { dev, ino, INTEREST_MASK };
168: int rc = ioctl(imonfd, IMONIOC_REVOKE, &rv);
169: if (rc < 0) {
170: Log::perror("IMONIOC_REVOKE on \"%s\" failed", name);
171: return BAD;
172: }
173: Log::debug("told imon to forget \"%s\"", name);
174: return OK;
175: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>