[BACK]Return to IMonLinux.c++ CVS log [TXT][DIR] Up to [Development] / fam / fam

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>