func listen_events(mount_point string, stop chan bool) chan map[event]bool { log.Println("monitor: listen_events start") nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY) check(err) err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT, fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point) check(err) events_chan := make(chan map[event]bool, 1) go func() { events := make(map[event]bool, 1) s := false for !s { select { case <-stop: s = true default: data, err := nd.GetEvent() check(err) path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd())) check(err) e := event{data.Pid, path} data.File.Close() events[e] = true } } events_chan <- events }() return events_chan }
func listen_events(mount_point string, stop chan bool) chan map[event]bool { log.Println("monitor: listen_events start") nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY) check(err) err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT, fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point) check(err) events_chan := make(chan map[event]bool, 1) go func() { log.Println("monitor: listen_events worker starting") events := make(map[event]bool, 1) eventChan := make(chan event) go func() { for { data, err := nd.GetEvent() check(err) path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd())) check(err) e := event{data.Pid, path} data.File.Close() eventChan <- e } }() s := false for !s { select { case <-time.After(20 * time.Second): log.Println("monitor: listen_events - event timeout...") s = true case <-stop: log.Println("monitor: listen_events stopping...") s = true case e := <-eventChan: events[e] = true log.Printf("monitor: listen_events event => %#v\n", e) } } log.Printf("monitor: listen_events sending %v events...\n", len(events)) events_chan <- events }() return events_chan }
//func listen_events(mount_point string, stopChan chan bool) chan map[event]bool { func listen_events(mount_point string, stopChan chan bool) <-chan *monitorReport { log.Println("monitor: listen_events start") nd, err := fanotify.Initialize(fanotify.FAN_CLASS_NOTIF, os.O_RDONLY) check(err) err = nd.Mark(fanotify.FAN_MARK_ADD|fanotify.FAN_MARK_MOUNT, fanotify.FAN_MODIFY|fanotify.FAN_ACCESS|fanotify.FAN_OPEN, -1, mount_point) check(err) //events_chan := make(chan map[event]bool, 1) events_chan := make(chan *monitorReport, 1) go func() { log.Println("monitor: listen_events worker starting") //events := make(map[event]bool, 1) report := &monitorReport{ MonitorPid: os.Getpid(), MonitorParentPid: os.Getppid(), ProcessFiles: make(map[string]map[string]*fileInfo), } eventChan := make(chan event) go func() { var eventId uint32 = 0 for { data, err := nd.GetEvent() check(err) //log.Printf("TMP: monitor: listen_events: data.Mask =>%x\n",data.Mask) if (data.Mask & fanotify.FAN_Q_OVERFLOW) == fanotify.FAN_Q_OVERFLOW { log.Println("monitor: listen_events: overflow event") continue } doNotify := false isRead := false isWrite := false if (data.Mask & fanotify.FAN_OPEN) == fanotify.FAN_OPEN { //log.Println("TMP: monitor: listen_events: file open") doNotify = true } if (data.Mask & fanotify.FAN_ACCESS) == fanotify.FAN_ACCESS { //log.Println("TMP: monitor: listen_events: file read") isRead = true doNotify = true } if (data.Mask & fanotify.FAN_MODIFY) == fanotify.FAN_MODIFY { //log.Println("TMP: monitor: listen_events: file write") isWrite = true doNotify = true } path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd())) check(err) //log.Println("TMP: monitor: listen_events: file path =>",path) data.File.Close() if doNotify { eventId++ e := event{Id: eventId, Pid: data.Pid, File: path, IsRead: isRead, IsWrite: isWrite} eventChan <- e } } }() s := false for !s { select { //case <-time.After(110 * time.Second): // log.Println("monitor: listen_events - event timeout...") // s = true case <-stopChan: log.Println("monitor: listen_events stopping...") s = true case e := <-eventChan: report.EventCount++ //log.Println("TMP: monitor: listen_events: event ",report.EventCount) if e.Id == 1 { //first event represents the main process if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) { report.MainProcess = pinfo report.Processes = make(map[string]*processInfo) report.Processes[strconv.Itoa(int(e.Pid))] = pinfo //log.Println("TMP: monitor: listen_events: (1) adding pi for ", // e.Pid,"info:",report.Processes[strconv.Itoa(int(e.Pid))]) } } else { if _, ok := report.Processes[strconv.Itoa(int(e.Pid))]; !ok { if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) { report.Processes[strconv.Itoa(int(e.Pid))] = pinfo //log.Println("TMP: monitor: listen_events: (2) adding pi for ", // e.Pid,"info:",report.Processes[strconv.Itoa(int(e.Pid))]) } } } if _, ok := report.ProcessFiles[strconv.Itoa(int(e.Pid))]; !ok { report.ProcessFiles[strconv.Itoa(int(e.Pid))] = make(map[string]*fileInfo) //log.Println("TMP: monitor: listen_events: adding pf for ",e.Pid) } if existingFi, ok := report.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File]; !ok { fi := &fileInfo{ EventCount: 1, Name: e.File, } if e.IsRead { fi.ReadCount = 1 } if e.IsWrite { fi.WriteCount = 1 } if pi, ok := report.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) { fi.ExeCount = 1 } report.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File] = fi } else { existingFi.EventCount++ if e.IsRead { existingFi.ReadCount++ } if e.IsWrite { existingFi.WriteCount++ } if pi, ok := report.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) { existingFi.ExeCount++ } } log.Printf("monitor: listen_events event => %#v\n", e) } } log.Printf("monitor: listen_events - sending report (processed %v events)...\n", report.EventCount) events_chan <- report }() return events_chan }
func Run(mountPoint string, stopChan chan struct{}) <-chan *report.FanMonitorReport { log.Info("fanmon: starting...") nd, err := fanapi.Initialize(fanapi.FAN_CLASS_NOTIF, os.O_RDONLY) utils.FailOn(err) err = nd.Mark(fanapi.FAN_MARK_ADD|fanapi.FAN_MARK_MOUNT, fanapi.FAN_MODIFY|fanapi.FAN_ACCESS|fanapi.FAN_OPEN, -1, mountPoint) utils.FailOn(err) eventsChan := make(chan *report.FanMonitorReport, 1) go func() { log.Debug("fanmon: fanRunMonitor worker starting") fanReport := &report.FanMonitorReport{ MonitorPid: os.Getpid(), MonitorParentPid: os.Getppid(), ProcessFiles: make(map[string]map[string]*report.FileInfo), } eventChan := make(chan Event) go func() { log.Debug("fanmon: fanRunMonitor worker (monitor) starting") var eventID uint32 for { data, err := nd.GetEvent() utils.FailOn(err) log.Debugf("fanmon: data.Mask =>%x\n", data.Mask) if (data.Mask & fanapi.FAN_Q_OVERFLOW) == fanapi.FAN_Q_OVERFLOW { log.Debug("fanmon: overflow event") continue } doNotify := false isRead := false isWrite := false if (data.Mask & fanapi.FAN_OPEN) == fanapi.FAN_OPEN { log.Debug("fanmon: file open") doNotify = true } if (data.Mask & fanapi.FAN_ACCESS) == fanapi.FAN_ACCESS { log.Debug("fanmon: file read") isRead = true doNotify = true } if (data.Mask & fanapi.FAN_MODIFY) == fanapi.FAN_MODIFY { log.Debug("fanmon: file write") isWrite = true doNotify = true } path, err := os.Readlink(fmt.Sprintf("/proc/self/fd/%d", data.File.Fd())) utils.FailOn(err) log.Debug("fanmon: file path =>", path) data.File.Close() if doNotify { eventID++ e := Event{ID: eventID, Pid: data.Pid, File: path, IsRead: isRead, IsWrite: isWrite} eventChan <- e } } }() done: for { select { case <-stopChan: log.Info("fanmon: stopping...") break done case e := <-eventChan: fanReport.EventCount++ log.Debug("fanmon: event ", fanReport.EventCount) if e.ID == 1 { //first event represents the main process if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) { fanReport.MainProcess = pinfo fanReport.Processes = make(map[string]*report.ProcessInfo) fanReport.Processes[strconv.Itoa(int(e.Pid))] = pinfo } } else { if _, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; !ok { if pinfo, err := getProcessInfo(e.Pid); (err == nil) && (pinfo != nil) { fanReport.Processes[strconv.Itoa(int(e.Pid))] = pinfo } } } if _, ok := fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))]; !ok { fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))] = make(map[string]*report.FileInfo) } if existingFi, ok := fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File]; !ok { fi := &report.FileInfo{ EventCount: 1, Name: e.File, } if e.IsRead { fi.ReadCount = 1 } if e.IsWrite { fi.WriteCount = 1 } if pi, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) { fi.ExeCount = 1 } fanReport.ProcessFiles[strconv.Itoa(int(e.Pid))][e.File] = fi } else { existingFi.EventCount++ if e.IsRead { existingFi.ReadCount++ } if e.IsWrite { existingFi.WriteCount++ } if pi, ok := fanReport.Processes[strconv.Itoa(int(e.Pid))]; ok && (e.File == pi.Path) { existingFi.ExeCount++ } } } } log.Debugf("fanmon: sending report (processed %v events)...\n", fanReport.EventCount) eventsChan <- fanReport }() return eventsChan }