2016-04-18 15 views
0

私はファンタジーにする初心者です。ファイルを開くと、fanotifyイベントの処理中にシステムがハングアップする

ファイルのオープンとクローズのイベントを処理しながら、ファイルに情報を書き込むためにfanotifyのマンページのexampleを使用しました。 'fopen'へのシステムコールにより、システムがハングします。 'FAN_OPEN_PERM'を 'FAN_OPEN'に変更したところ、それはすべてOKです。 'FAN_OPEN_PERM'フラグはログに記録できません。

私はfanotify techを使用していないことがありますか?または fanotifyの処理に制限がありますか?

また、fanotifyイベントを処理している間にファイルをログに記録する良いアイデアはありますか?

「3.16.0-70-ジェネリック」カーネルバージョンの「Ubuntu 14.04.3 64bit」でコンパイルしてテストしました。

私はこのようないくつかのコードを追加しました:

static void PrintToFile(const char *pszMsg) 
{ 
    int err = 0; 
    if(NULL == pszMsg) { 
     printf("invalid message\n"); 
     return ; 
    } 

    FILE *fp = fopen("/tmp/fanotify.log", "a+"); // <= here, system hangs 
    if(NULL == fp) { 
     err = errno; 
     printf("file open fail (%d) \n", err); 
     return ; 
    } 
    size_t len = strlen(pszMsg); 
    feesk(fp, 0L, SEEK_END); 
    fwrite(pszMsg, 1, len, fp); 
    fclose(fp); 
} 

、その後、私は 'handle_events' fucntionに次のコードを追加し

{ 
    char strBuf[PATH_MAX]; 
    sprintf(strBuf, "File %s\n", path); 
    PrintToFile(strBuf); 
} 

modifed 'handle_events' 関数を参照してください

static void 
handle_events(int fd) 
{ 
     const struct fanotify_event_metadata *metadata; 
     struct fanotify_event_metadata buf[200]; 
     ssize_t len; 
     char path[PATH_MAX]; 
     ssize_t path_len; 
     char procfd_path[PATH_MAX]; 
     struct fanotify_response response; 

     /* Loop while events can be read from fanotify file descriptor */ 

     for(;;) { 

      /* Read some events */ 

      len = read(fd, (void *) &buf, sizeof(buf)); 
      if (len == -1 && errno != EAGAIN) { 
       perror("read"); 
       exit(EXIT_FAILURE); 
      } 

      /* Check if end of available data reached */ 

      if (len <= 0) 
       break; 

      /* Point to the first event in the buffer */ 

      metadata = buf; 

      /* Loop over all events in the buffer */ 

      while (FAN_EVENT_OK(metadata, len)) { 

       /* Check that run-time and compile-time structures match */ 

       if (metadata->vers != FANOTIFY_METADATA_VERSION) { 
        fprintf(stderr, 
          "Mismatch of fanotify metadata version.\n"); 
        exit(EXIT_FAILURE); 
       } 

       /* metadata->fd contains either FAN_NOFD, indicating a 
        queue overflow, or a file descriptor (a nonnegative 
        integer). Here, we simply ignore queue overflow. */ 

       if (metadata->fd >= 0) { 

        /* Handle open permission event */ 

        if (metadata->mask & FAN_OPEN_PERM) { 
         printf("FAN_OPEN_PERM: "); 

         /* Allow file to be opened */ 

         response.fd = metadata->fd; 
         response.response = FAN_ALLOW; 
         write(fd, &response, 
          sizeof(struct fanotify_response)); 
        } 

        /* Handle closing of writable file event */ 

        if (metadata->mask & FAN_CLOSE_WRITE) 
         printf("FAN_CLOSE_WRITE: "); 

        /* Retrieve and print pathname of the accessed file */ 

        snprintf(procfd_path, sizeof(procfd_path), 
          "/proc/self/fd/%d", metadata->fd); 
        path_len = readlink(procfd_path, path, 
             sizeof(path) - 1); 
        if (path_len == -1) { 
         perror("readlink"); 
         exit(EXIT_FAILURE); 
        } 

        path[path_len] = '\0'; 
        printf("File %s\n", path); 

        //these code snipptets are added 
        { 
         char strBuf[PATH_MAX]; 
         sprintf(strBuf, "File %s\n", path); 
         PrintToFile(strBuf); 
        } 

        /* Close the file descriptor of the event */ 

        close(metadata->fd); 
       } 

       /* Advance to next event */ 

       metadata = FAN_EVENT_NEXT(metadata, len); 
      } 
     } 
    } 

答えて

1

「ファイルを開く」モニタハンドラでファイルを開くと、無限ループが発生することがあります。印刷イベントの原因を無視するためにPrintToFileを呼び出すブロックの前に、ブロックの前に if (metadata->pid != getpid()) を追加してください。

関連する問題