É possível criar um arquivo não vazio sem write_close e renomear evento?

5

A razão pela qual estou perguntando é porque estou usando iwatch (para não confundir com um dispositivo de gadget) observe os eventos do sistema de arquivos (no meu caso - criação / renomeação de arquivos).

O que não consigo explicar é este log:

/path/to/file.ext.filepart 0 IN_MODIFY 
/path/to/file.ext.filepart 0 IN_MODIFY 
/path/to/file.ext.filepart 0 IN_MODIFY 
/path/to/file.ext.filepart 0 IN_MODIFY 
/path/to/file.ext.filepart 0 IN_CLOSE_WRITE 
/path/to/file.ext 0 IN_CREATE 
/path/to/file.ext.filepart 0 IN_DELETE 
/path/to/file.ext 0 IN_ATTRIB 

Para obtê-lo, copiei uma file.ext de uma máquina remota usando o WinSCP com a opção de criação de arquivo temporário ativada (para que não houvesse nenhum arquivo file.ext , no caso de a transferência ser encerrada ou o arquivo completo estava no destino).

E o que me confunde é que o /path/to/file.ext só é criado IN_CREATE e seus atributos foram modificados IN_ATTRIB (não sei quais, mas acho que é lá que acontece toda a mágica).

O mais estranho aqui é que:

  1. O file.ext não é um resultado da movimentação de file.ext.filepart - haveria um evento de movimento diferente
  2. O file.ext não é um resultado de copiar file.ext.filepart - haveria muitos eventos de gravação seguindo por IN_CLOSE_WRITE

Então, a minha pergunta é: o que está acontecendo aqui: como o file.ext foi criado com o conteúdo sem uma renomeação ou cópia de dados explícita?

    
por zerkms 01.04.2015 / 23:55

1 resposta

10
$ inotifywait -m /tmp
Setting up watches.
Watches established.
/tmp/ CREATE file.ext.filepart
/tmp/ OPEN file.ext.filepart
/tmp/ MODIFY file.ext.filepart
/tmp/ CLOSE_WRITE,CLOSE file.ext.filepart
/tmp/ CREATE file.ext
/tmp/ DELETE file.ext.filepart

Transcrição da execução

$ echo hello >/tmp/file.ext.filepart
$ ln /tmp/file.ext.filepart /tmp/file.ext         
$ rm /tmp/file.ext.filepart

Mover um arquivo gera um evento move , mas a criação de um link físico gera o mesmo evento create da criação de um novo arquivo vazio (como mkfifo e outras formas de criar arquivos).

Por que o servidor SCP ou SFTP cria um link físico e, em seguida, remove o arquivo temporário em vez de mover o arquivo temporário para o local? No código-fonte do OpenSSH (portátil 6.0), em sftp-server.c , na função process_rename , vejo o seguinte código (reformatado e simplificado para ilustrar a parte que quero mostrar):

if (S_ISREG(sb.st_mode)) {
    /* Race-free rename of regular files */
    if (link(oldpath, newpath) == -1) {
         if (errno == EOPNOTSUPP || errno == ENOSYS) {
            /* fs doesn't support links, so fall back to stat+rename.  This is racy. */
            if (stat(newpath, &st) == -1) {
                rename(oldpath, newpath) == -1)
            }
        }
    } else {
        unlink(newpath);
    }
}

Ou seja: tente criar um link físico do nome do arquivo temporário para o nome do arquivo desejado e, em seguida, remova o arquivo temporário. Se a criação do link físico não funcionar porque o sistema operacional ou o sistema de arquivos não suportam isso, recorra a um método diferente: teste se o arquivo desejado existe e, se não, renomeie o arquivo temporário. Portanto, o objetivo é renomear o arquivo temporário para seu local final sem arriscar sobrescrever um arquivo que possa ter sido criado enquanto a cópia estava em andamento. A renomeação não seria feita porque rename sobrescreve o arquivo de destino, se existir.

    
por 02.04.2015 / 00:25