[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     ! 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>