2013-11-24 2 views
0

Я пытался мою руку на 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 

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

ответ

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); 
+0

Понятно, спасибо. – Witiko

Смежные вопросы