Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inotify don't treat vim editting as a modification event

Tags:

linux

vim

inotify

my example code below watches a file for being modified. let's say the file being wathched is foo.txt, and the binary name came out from the sample code is inotify. I did two test for the sample code.

test1:
1) ./inotify foo.txt
2) echo "hello" > foo.txt
then everything works fine,and "file modified" has been printed out.

test2:
1) ./infity foo.txt
2) vim foo.txt
3) edit somehow and save,but don't quit vim
the printed out line is unknown Mask 0x00008000, checked out the inotify header file found this event mask mean IN_CLOSE_WRITE.

from my point of view, "edit and save" just menas modify. but obvisously the inotify code has a different interpration for it. it's strange for me, can anyone help to explain the things behind?

#include <sys/inotify.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>


int main(int argc, char **argv)
{
  int fdnotify = -1; 

  if (argc !=2) {
    fprintf(stderr, "usage: ./inotify dir_name\n");
    exit(1);
  }

  printf("argc is %d\n", argc);

  fdnotify = inotify_init();
  if (fdnotify < 0) {
    fprintf(stderr, "inotity_init failed: %s\n", strerror(errno));
  }

  int wd = inotify_add_watch(fdnotify, argv[1], IN_MODIFY);
  if (wd < 0) {
    fprintf(stderr, "inotify_add_watch failed: %s\n", strerror(errno));
  }

  while(1) {
    char buffer[4096];
    struct inotify_event *event = NULL;

    int len = read(fdnotify, buffer, sizeof(buffer));

    if (len < 0) {
      fprintf(stderr, "read error %s\n", strerror(errno));
    }   

    event = (struct inotify_event *) buffer;

    while(event != NULL) {
      if ((event->mask & IN_MODIFY)  ) { 
        printf("File modified %s\n", event->name);
      } else {
 printf("unknown Mask 0x%.8x\n", event->mask);
      }
      len -= sizeof(*event) + event->len;

      if (len > 0)
        event = ((void *) event) + sizeof(event) + event->len;
      else
        event = NULL;
    }
  }
}
like image 767
Haiyuan Zhang Avatar asked Nov 09 '12 17:11

Haiyuan Zhang


2 Answers

Vim is a program that does not directly save to the file while you save the file. It creates a temporary file usually named .filename.swp and only when you close vim this file gets renamed to filename. From the inotify's FAQ:

The IN_MODIFY event is emitted on a file content change (e.g. via the write() syscall) while IN_CLOSE_WRITE occurs on closing the changed file. It means each change operation causes one IN_MODIFY event (it may occur many times during manipulations with an open file) whereas IN_CLOSE_WRITE is emitted only once (on closing the file).

So the event you get actually makes sense. Lets say that you have a file called filename. When you open the file filename another file is created named .filename.swp. All modifications you perform on this file would, if monitored, generate a number of IN_MODIFY events. When you actually save, what ends up happening is, vim renames this file and closes it, thus generating the IN_CLOSE_WRITE event.

like image 122
Florin Stingaciu Avatar answered Nov 03 '22 19:11

Florin Stingaciu


I thought Mask 0x00008000 was IN_IGNORED According to inotify.h:

#define IN_CLOSE_WRITE   0x00000008 /* Writtable file was closed.  */
#define IN_IGNORED   0x00008000 /* File was ignored.  */

Is it posible that the event mask is an IN_IGNORED?

like image 43
mar_sanbas Avatar answered Nov 03 '22 19:11

mar_sanbas