Onde os metadados vão quando você salva um arquivo?

29

Digamos que Johnny faça um arquivo EMPTY. É chamado foobar.py . Quando Johnny permite que ele seja executado, ele executa chmod 755 foobar.py . O arquivo agora tem os metadados de

-rw-r--r-- 1 johnny staff    0 Dec 27 22:53 foobar.py

Onde estão todos os metadados armazenados nesse arquivo? O tamanho do arquivo é 0, então como ele mantém os metadados quando é transferido para outra unidade?

    
por juniorRubyist 28.12.2016 / 07:55

3 respostas

42

Não é armazenado no arquivo. Ele é armazenado no sistema de arquivos, e todos os parâmetros são copiados manualmente um por um (embora alguns não possam ser copiados de forma alguma).

Ou seja, a maioria dos sistemas operacionais não tem uma chamada "copiar arquivo com metadados". O programa de cópia de arquivos simplesmente cria um novo arquivo chamado foobar.py , copia os 0 bytes inteiros de dados e, em seguida, usa utime () ou SetFileTime ( ) para fazer com que a sua hora de modificação pareça a mesma que a do original. Da mesma forma, as permissões de arquivo seriam "copiadas", definindo-as novamente usando chmod () ou copiando o atributo POSIX ACL.

Alguns metadados não são copiados. A definição de propriedade requer privilégios de root, de modo que as cópias dos arquivos de outra pessoa pertençam a você e ocupem sua cota de disco sua . O ctime (tempo de alteração do atributo) é impossível de ser configurado manualmente nos Unixes; btime (horário de nascimento / criação) geralmente não é copiado.

Compare cp -a foo bar (que copia metadados) e cp foo bar (que não):

$ strace -v cp foo bar
…
open("foo", O_RDONLY)                   = 3
open("bar", O_WRONLY|O_TRUNC)           = 4
read(3, "test\n", 131072)               = 5
write(4, "test\n", 5)                   = 5
read(3, "", 131072)                     = 0
close(4)                                = 0
close(3)                                = 0
…
$ strace -v cp -a foo bar
…
 -- original metadata is retrieved
lstat("foo", {st_dev=makedev(254, 0), st_ino=60569468, st_mode=S_IFREG|0644,
             st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8,
             st_size=5, st_atime=2016-12-28T09:16:59+0200.879714332,
             st_mtime=2016-12-28T09:16:55+0200.816363098,
             st_ctime=2016-12-28T09:16:55+0200.816363098}) = 0
 -- data is copied
open("foo", O_RDONLY|O_NOFOLLOW)        = 3
open("bar", O_WRONLY|O_TRUNC)           = 4
read(3, "test\n", 131072)               = 5
write(4, "test\n", 5)                   = 5
read(3, "", 131072)                     = 0
 -- modifiction time is copied
utimensat(4, NULL, [{tv_sec=1482909419, tv_nsec=879714332},
                    {tv_sec=1482909415, tv_nsec=816363098}], 0) = 0
 -- ownership is copied (only with 'sudo [strace] cp')
fchown(4, 1000, 1000)                   = 0
 -- extended attributes are copied (xdg.origin.url is set by browsers, wget)
flistxattr(3, NULL, 0)                  = 0
flistxattr(3, "user.xdg.origin.url
$ strace -v cp foo bar
…
open("foo", O_RDONLY)                   = 3
open("bar", O_WRONLY|O_TRUNC)           = 4
read(3, "test\n", 131072)               = 5
write(4, "test\n", 5)                   = 5
read(3, "", 131072)                     = 0
close(4)                                = 0
close(3)                                = 0
…
", 20) = 20 fgetxattr(3, "user.xdg.origin.url", "https://superuser.com/", 22) = 22 fsetxattr(4, "user.xdg.origin.url", "https://superuser.com/", 22, 0) = 0 -- POSIX ACLs are not present, so a basic ACL is built from st_mode -- (in this case, a simple fchmod() would work as well) fgetxattr(3, "system.posix_acl_access", 0x7ffc87a50be0, 132) = -1 ENODATA (No data available) fsetxattr(4, "system.posix_acl_access", "
$ strace -v cp -a foo bar
…
 -- original metadata is retrieved
lstat("foo", {st_dev=makedev(254, 0), st_ino=60569468, st_mode=S_IFREG|0644,
             st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8,
             st_size=5, st_atime=2016-12-28T09:16:59+0200.879714332,
             st_mtime=2016-12-28T09:16:55+0200.816363098,
             st_ctime=2016-12-28T09:16:55+0200.816363098}) = 0
 -- data is copied
open("foo", O_RDONLY|O_NOFOLLOW)        = 3
open("bar", O_WRONLY|O_TRUNC)           = 4
read(3, "test\n", 131072)               = 5
write(4, "test\n", 5)                   = 5
read(3, "", 131072)                     = 0
 -- modifiction time is copied
utimensat(4, NULL, [{tv_sec=1482909419, tv_nsec=879714332},
                    {tv_sec=1482909415, tv_nsec=816363098}], 0) = 0
 -- ownership is copied (only with 'sudo [strace] cp')
fchown(4, 1000, 1000)                   = 0
 -- extended attributes are copied (xdg.origin.url is set by browsers, wget)
flistxattr(3, NULL, 0)                  = 0
flistxattr(3, "user.xdg.origin.url%pre%", 20) = 20
fgetxattr(3, "user.xdg.origin.url", "https://superuser.com/", 22) = 22
fsetxattr(4, "user.xdg.origin.url", "https://superuser.com/", 22, 0) = 0
 -- POSIX ACLs are not present, so a basic ACL is built from st_mode
 -- (in this case, a simple fchmod() would work as well)
fgetxattr(3, "system.posix_acl_access", 0x7ffc87a50be0, 132) = -1 ENODATA (No data available)
fsetxattr(4, "system.posix_acl_access", "%pre%%pre%%pre%%pre%%pre%7777%pre%%pre%7777 %pre%%pre%7777", 28, 0) = 0
close(4)                                = 0
close(3)                                = 0
…
%pre%%pre%%pre%%pre%7777%pre%%pre%7777 %pre%%pre%7777", 28, 0) = 0 close(4) = 0 close(3) = 0 …
    
por 28.12.2016 / 08:15
12

Geralmente difere do sistema de arquivos para o sistema de arquivos onde os metadados são armazenados. Na família ext2 de sistemas de arquivos, os metadados que você mencionou (proprietário, grupo, permissões, tempo) são armazenados no inode . O inode também armazena (ponteiros para) os blocos que o arquivo ocupa no disco. O inode não não armazena o nome do arquivo.

Você pode acessar esses dados com a chamada do sistema stat ( man 2 stat ) e usar a ferramenta stat para imprimi-la ( man stat ). Uma descrição detalhada dos campos inode pode ser encontrada em linux/include/linux/fs.h na fonte do kernel.

Existem outros tipos de metadados (por exemplo, permissões de ACL ) que são armazenados em locais diferentes.

Metadados não são copiados por padrão quando você copia o arquivo. Em vez disso, um novo arquivo com valores de metadados padrão é criado. Há várias opções para cp ( -p , --preserve ) que instruem cp a copiar metadados, lendo os metadados antigos com stat e modificando os novos metadados de acordo.

    
por 28.12.2016 / 10:11
4

Dependendo do sistema de arquivos, as áreas são reservadas (semi-) estaticamente ou dinamicamente para conter metadados como permissões, tamanho e outros (às vezes, o nome do arquivo também).

No Unix, os metadados são armazenados no inode que controla a área de dados onde o arquivo reside ( enquanto nomes de arquivos e números de inodes relacionados são armazenados em uma entrada de diretório ).

Em algumas entradas do diretório de sistemas de arquivos, existem arquivos como qualquer outro, mas ocultos da visualização. FAT e FAT32 são tais sistemas de arquivos (o diretório raiz do FAT é "especial"). Ao criar um arquivo, você adiciona / edita uma entrada no arquivo que descreve a pasta em que o arquivo reside. Cada entrada é grande o suficiente para armazenar tamanho de arquivo, nome e data, e nada mais (nomes longos ocupando múltiplas entradas; o tamanho de entrada padrão de 32 bytes pode conter um único nome no antigo formato de 8 + 3 caracteres. , assumindo que minha memória está funcionando). O sistema ext é semelhante, mas a entrada de diretório é dimensionada dinamicamente e contém apenas o nome e o ponteiro inode; todas as outras informações estão no inode. Dessa forma, duas entradas podem apontar para o mesmo arquivo, o que é útil para gerenciar arquivos duplicados.

Em alguns sistemas de arquivos, os inodes podem ser grandes o suficiente para conter uma pequena quantidade de dados, além dos metadados, para que, se o arquivo couber, não ocupem espaço extra em disco. Você cria um arquivo de 45 bytes e o espaço livre em disco não é alterado; esses bytes são armazenados dentro do inode. Eu acho que a família ext * suporta isso (e também o NTFS). Isso ajuda a gerenciar um grande número de arquivos muito pequenos.

Em outros sistemas de arquivos, existe um sistema de arquivos "fantasma" ao longo do principal, que armazena esses atributos extras. Não apenas as informações do arquivo, mas possivelmente os ícones de arquivo também.

Alguns sistemas têm os dois: o NTFS tem os metadados completos do diretório funcionando de forma semelhante a inode e a possibilidade de criar fluxos de dados alternativos contendo informações adicionais que (aparentemente) não alteram nada no arquivo" principal ".

    
por 28.12.2016 / 14:35