Re: [OT] C e inotify
Il 22 luglio 2016 17:32, Alessandro Baggi <alessandro.baggi@gmail.com>
ha scritto:
> La modifica del file, modifica attributi e spostamento vengono rilevati
> mentre la cancellazione (con rm, unlink) non viene rilevato con evento
> IN_DELETE_SELF ma IN_ATTRIB.
[...]
> Dato che su questo specifico file è aperto un file descriptor, e avendo
> letto che il delete_self non viene rilevato con un fd aperto sul file, ho
> provato anche a non aprire il file in lettura (per altre operazioni) senza
> esito positivo.
Non riesco a riprodurre il tuo problema, quello che vedo io è questo:
$ touch file
$ ./a.out file
$ rm file
file 00000004: IN_ATTRIB
file 00000400: IN_DELETE_SELF
file 00008000: IN_IGNORED
Cioè, vedo anche io un IN_ATTRIB, ma seguito come mi aspetto da IN_DELETE_SELF
e IN_IGNORED. Non è che in uscita dalla read() leggi solo il primo e
scarti gli altri?
> Ho notato anche che la modifica del file con un editor (nel mio caso vi) non
> riporta un evento modify ma un move e un attrib (forse perche vi crea un
> file in /tmp e poi lo sposta sul'originale?)
Quasi. Al momento di salvare il file, vim lo rinomina in 'nomefile~', crea un
nuovo file 'nomefile' e se tutto va a buon fine elimina 'nomefile~'.
Per questo motivo, non puoi aspettarti un IN_MODIFY perchè una volta che vim
ha fatto rename(), il tuo processo continuerà ad osservare 'nomefile~' che non
verrà toccato se non per fare unlink() alla fine.
La sequenza che vedo salvando un file con vim è questa:
$ ./a.out file
file 00000800: IN_MOVE_SELF
file 00000004: IN_ATTRIB
file 00000400: IN_DELETE_SELF
file 00008000: IN_IGNORED
cioè il risultato di rename() e unlink()
Ti allego il file sorgente con cui ho fatto le prove: vedi sulla tua macchina
come si comporta.
Ciao
Mattia
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd, wd;
char buf[4096]
__attribute__ ((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *event;
ssize_t len;
char *ptr;
if (argc < 2) {
fprintf(stderr, "Usage: %s PATH\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = inotify_init();
if (fd == -1) {
fprintf(stderr, "inotify_init failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
wd = inotify_add_watch(fd, argv[1], IN_ATTRIB | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF);
if (wd == -1) {
fprintf(stderr, "Cannot watch %s: %s\n", argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
while(1) {
len = read(fd, buf, sizeof buf);
if (len == -1) {
fprintf(stderr, "read failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
for (ptr = buf; ptr < buf + len;
ptr += sizeof(struct inotify_event) + event->len) {
event = (const struct inotify_event *) ptr;
printf("%s %08X:", argv[1], event->mask);
if (event->mask & IN_ATTRIB)
printf(" IN_ATTRIB ");
if (event->mask & IN_DELETE_SELF)
printf(" IN_DELETE_SELF ");
if (event->mask & IN_MODIFY)
printf(" IN_MODIFY ");
if (event->mask & IN_MOVE_SELF)
printf(" IN_MOVE_SELF ");
if (event->mask & IN_IGNORED)
printf(" IN_IGNORED ");
printf("\n");
}
}
close(fd);
exit(EXIT_SUCCESS);
}
Reply to: