Чтение дескриптора файла inotify заполняет буфер бинарным мусором

Я пробовал свои силы в inotify, и следующий фрагмент кода, по моему мнению, будет хорошей демонстрацией его возможностей:

#include <sys/inotify.h>  /* inotify_init(), inotify_add_watch(), IN_* */
#include <stdlib.h>       /* EXIT_SUCCESS, EXIT_FAILURE, malloc() */
#include <stdio.h>        /* printf(), puts(), perror() */
#include <unistd.h>       /* read() */
#include <sys/ioctl.h>    /* ioctl, FIONREAD */
#define PTRY(expr)  if((expr) == -1)
#define PGOTO(label, msg) do{\
    perror(msg);\
    goto label;\
  } while(0)


int main(void) {

  int fd;
  PTRY(fd = inotify_init())                       PGOTO(failure, "inotify_init");
  PTRY(inotify_add_watch(fd, ".", IN_ALL_EVENTS)) PGOTO(failure, "inotify_add_watch");

  while(1) {

    unsigned int avail;                           /* We find out how large a buffer we need */
    PTRY(ioctl(fd, FIONREAD, &avail))             PGOTO(failure, "ioctl");

    char buffer[avail];
    ssize_t count = read(fd, buffer, avail);      /* We fill the buffer */
    if(avail > 0 && count < avail)                PGOTO(failure, "read");

    printf("Avail: %d, Read: %d\n", (int)avail, (int)count);
    if(avail > 0) puts("");

    for(ssize_t i = 0; i < count; ) {             /* For each event structure in the buffer */

      struct inotify_event* event = (struct inotify_event*)buffer + i;
      printf("Byte: %d - %d out of %d\n", (int)i, (int)(sizeof(struct inotify_event) + event->len), (int)count);

      if(event->len > 0) {                        /* We print its contents */
        printf("Name: %s\n",   event->name);
      } printf("Cookie: %d\n", event->cookie);

      if(event->mask & IN_ACCESS)         puts("IN_ACCESS");
      if(event->mask & IN_ATTRIB)         puts("IN_ATTRIB");
      if(event->mask & IN_CLOSE_WRITE)    puts("IN_CLOSE_WRITE");
      if(event->mask & IN_CLOSE_NOWRITE)  puts("IN_CLOSE_NOWRITE");
      if(event->mask & IN_CREATE)         puts("IN_CREATE");
      if(event->mask & IN_DELETE)         puts("IN_DELETE");
      if(event->mask & IN_DELETE_SELF)    puts("IN_DELETE_SELF");
      if(event->mask & IN_MODIFY)         puts("IN_MODIFY");
      if(event->mask & IN_MOVE_SELF)      puts("IN_MOVE_SELF");
      if(event->mask & IN_MOVED_FROM)     puts("IN_MOVED_FROM");
      if(event->mask & IN_MOVED_TO)       puts("IN_MOVED_TO");
      if(event->mask & IN_OPEN)           puts("IN_OPEN");
      puts("");

      i += sizeof(struct inotify_event) + event->len;

    }

  }

  return EXIT_SUCCESS;

  failure:
    return EXIT_FAILURE;

}

Однако я получаю некоторые посторонние записи от вызова read(2), заполненные двоичным мусором. Прилагается вывод программы при вызове cat notifyTest.c из оболочки:

Avail: 0, Read: -1
Avail: 64, Read: 64

Byte: 0 - 32 out of 64
Name: notifyTest.c
Cookie: 0
IN_OPEN

Byte: 32 - 32783 out of 64
Name: ▒▒▒
Cookie: 1726459283
IN_ACCESS
IN_ATTRIB
IN_CLOSE_WRITE
IN_CLOSE_NOWRITE
IN_CREATE
IN_DELETE
IN_DELETE_SELF
IN_MODIFY
IN_MOVE_SELF
IN_MOVED_FROM
IN_MOVED_TO
IN_OPEN

Avail: 0, Read: -1
Avail: 32, Read: 32

Byte: 0 - 32 out of 32
Name: notifyTest.c
Cookie: 0
IN_CLOSE_NOWRITE

Это может привести к нарушению кода, поскольку процесс будет сигнализирован SIGSEGV и остановлен при чтении event->name, если в границах статически выделенного буфера не будет завершающего символа '\0'.

Может ли это быть причудой, или я просто делаю что-то ужасно неправильно? Мой uname -a это:

Linux witiko-D830 3.8.0-32-generic #47-Ubuntu SMP Tue Oct 1 22:35:23 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

Буду признателен за любые подсказки, что могло пойти не так.


person Witiko    schedule 24.11.2013    source источник


Ответы (1)


Ваша проблема в этой строке:

 struct inotify_event* event = (struct inotify_event*)buffer + i;

Эта строка приводит указатель buffer к типу struct inotify_event*, а затем выполняет добавление i, что на вашей второй итерации равно 32. Затем значения увеличиваются на 32 * sizeof(struct inotify_event).

Исправление будет:

 struct inotify_event* event = (struct inotify_event*)(buffer + i);
person Macattack    schedule 24.11.2013