Pregunta

Resumen:Quiero conseguir el número de generación (i_generation) de un archivo en Linux (o al menos ext4) desde el espacio de usuario.O, alternativamente, el nacimiento de tiempo' (hora de creación del archivo).

Estoy tratando de escribir una bidireccional de archivos sincronización de programa (aka Unison), pero sin una base de datos central (fácil, sólo tienes que guardar los datos en la sincronización de las raíces) y por la preservación de archivo se mueve (muy, muy duro para conseguir la derecha si quieres apoyar a todos los extraños casos como mover un archivo de un directorio que se elimina después, por ejemplo).

Tener un modo para identificar los archivos de facilitaría MUCHO las cosas.Sé cómo conseguir el inodo y el número de dispositivo (a través de stat), pero como los inodos puede ser re-utilizado (lo he visto yo), quiero utilizar una forma más estable de identificación único.

He leído sobre el número de generación' que está siendo utilizado por NFS para identificar los archivos.En NFS, el (st_ino, i_generation) combinación se utiliza para identificar los identificadores de archivo a través de los reinicios y bloqueos en el servidor (o al menos para evitar que vuelva a utilizar el mismo identificador de archivo que conduce a la posible corrupción de datos).

No he tenido éxito en conseguir el número, sin embargo. Este ext4 documentación parece sugerir que el número puede ser obtenida a partir de un sistema de archivos ext4, pero no puedo poner mis manos en él desde el espacio de usuario (no voy a ejecutar este programa simple en el espacio del kernel).Ver EXT4_IOC_GETVERSION.No puedo encontrar el archivo de encabezado en mi sistema (LMDE, Debian testing).Hay dos opciones que pude encontrar:

  1. Pruebe a utilizar el uno en el núcleo produce un error diciendo que no debería ser utilizado desde el espacio de usuario.
  2. Trate de usar EXT2_IOC_GETVERSION en <linux/ext2_fs.h> - da EBADF (errno 9).Tal vez porque estoy tratando de conseguir EXT2 información desde un sistema de archivos EXT4?O tal vez estoy haciendo algo mal con ioctl, esta es la primera vez que estoy tratando de utilizar.El archivo se abre correctamente, porque la open la llamada devuelve 3 en mi caso (que debe ser válida).

el código:

#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <linux/ext2_fs.h>
#include <stdio.h>
#include <errno.h>

int main () {
    int fileno = open("generation.c", O_RDONLY);
    printf("fileno: %d\n", fileno);
    int generation = 0;
    if (ioctl(EXT2_IOC_GETVERSION, fileno, &generation)) {
        printf("errno: %d\n", errno);
    }
    printf("generation: %d\n", generation);
}

Este código le da un error (errno=9) en Ubuntu 12.04, en LMDE (Debian Testing) da un error del compilador (EXT2_IOC_GETVERSION no se encuentra).

Una alternativa sería la de conseguir que el tiempo de creación (crtime, o btime / de la hora de nacimiento) de los archivos, pero todos mis Googlear se ha convertido es que esto parece ser imposible de conseguir desde el espacio de usuario en Linux (IIRC FreeBSD dispone de un sistema de llamada por él).Yo preferiría crtime porque crtime puede ser más portable (para Windows) que un número de generación.

Sé que esto va a ser dependiente del sistema.Quiero tener una de reserva cuando hay un único inodo (o no inodo en todo, en el caso de la GRASA, que es común en las memorias USB) puede ser encontrado.

inotify no es una opción.Es un programa para sincronizar archivos después de que se han modificado, como rsync hace de una manera.No me gusta cómo Dropbox se queda en el fondo de la observación de los cambios en el archivo.

Si no hay manera de obtener estos números, también voy a aceptar eso como una respuesta (con la debida documentación de curso) :)

¿Fue útil?

Solución

He encontrado la solución.Cambié el fileno y el ioctl llame al (aparentemente C hace algunos conversión automática de tipo no).

El código de trabajo se parece a esto:

#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <linux/fs.h>
#include <stdio.h>
#include <errno.h>

int main () {
    int fileno = open("generation.c", O_RDONLY);
    printf("fileno: %d\n", fileno);
    int generation = 0;
    if (ioctl(fileno, FS_IOC_GETVERSION, &generation)) {
        printf("errno: %d\n", errno);
    }
    printf("generation: %d\n", generation);
}

El uso de FS_IOC_GETVERSION hace la llamada de trabajo para el común de los sistemas de archivos en Linux.Esto excluye vfat y ntfs (al menos eso parece en las fuentes del kernel, ni vfat ni fusible se enumeran allí), así que probablemente no apoyar la generación de números.

Este fragmento de coreutils (src/copiar.c en el archivo comprimido) me puso a pensar:

/* Perform the O(1) btrfs clone operation, if possible.
   Upon success, return 0.  Otherwise, return -1 and set errno.  */
static inline int
clone_file (int dest_fd, int src_fd)
{
#ifdef __linux__
# undef BTRFS_IOCTL_MAGIC
# define BTRFS_IOCTL_MAGIC 0x94
# undef BTRFS_IOC_CLONE
# define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int)
  return ioctl (dest_fd, BTRFS_IOC_CLONE, src_fd);
#else
  (void) dest_fd;
  (void) src_fd;
  errno = ENOTSUP;
  return -1;
#endif
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top