Como comandos como ls ou stat distinguem o tipo de arquivo?

0

Como comandos como ls ou stat distinguem o tipo de arquivo, se o objeto é um arquivo ou diretório?

Por exemplo, eu criei esses dois objetos, considerando o fato de que um diretório também é um arquivo ... com algumas regras especiais, eu quero saber como na saída do comando stat estes são rotulados como "diretório "e" arquivo vazio regular ".

$ mkdir testdir;touch testfile
$ stat testdir | head -2;stat testfile | head -2
 File: 'testdir'
 Size: 4096            Blocks: 8          IO Block: 4096   directory
 File: 'testfile'
 Size: 0               Blocks: 0          IO Block: 4096   regular empty file

Mais tarde, fiz um strace ao executar stat do diretório testdir e do arquivo testfile respectivamente. Na saída de rastreio, notei que estes

lstat("testdir/", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0

e

lstat("testfile", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0

Alguém, por favor, me diga como st_mode obtém esses valores S_IFDIR e S_IFREG .

Eu posso parecer confuso; Eu sou de fato.

    
por dee-muh n 23.12.2016 / 03:49

2 respostas

6

Vamos tentar confundir você. Em um inode , há um campo de 16 bits retornado pelo stat / lstat (e variantes de 64 bits) no st_mode. Desses 9 bits são usados para as permissões rwxrwxrwx, outros 3 para sticky bit , set group id (sgid) bit e set userid (suid) bit . Os outros 4 bits são usados para codificar algumas informações de tipo. Isso pode dizer que é um arquivo normal, um diretório, um dispositivo de bloco ou caractere, um pipe nomeado, etc. etc.

Então, se você criar um diretório, então esses 4 bits dizem que é um diretório. Você pode ver isso na saída strace ...

lstat("testdir/", {st_mode=S_IFDIR|0775, st_size=4096, ...})
                           ^^^^^^^ 4 bits showing the type is directory
                                   ^ 3 bits (this is octal) for suid/sgid/sticky
                                    ^^^ rwxrwxrwx info.
    
por 23.12.2016 / 06:02
0

Comandos ls , stat ou até file usam internamente a chamada do sistema C stat() para reunir os detalhes. Aqui as estruturas são definidas. Se você verificar os arquivos de estatísticas:

  • /usr/include/bits/stat.h
  • /usr/include/linux/stat.h

Os seguintes bits são definidos:

/* Encoding of the file mode.  */

#define __S_IFMT        0170000 /* These bits determine file type.  */

/* File types.  */
#define __S_IFDIR       0040000 /* Directory.  */
#define __S_IFCHR       0020000 /* Character device.  */
#define __S_IFBLK       0060000 /* Block device.  */
#define __S_IFREG       0100000 /* Regular file.  */
#define __S_IFIFO       0010000 /* FIFO.  */
#define __S_IFLNK       0120000 /* Symbolic link.  */
#define __S_IFSOCK      0140000 /* Socket.  */

the stat function will check the POSIX macros and compare to see if it is a regular file/ directory

#define S_ISLNK(m)      (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m)      (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m)     (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m)     (((m) & S_IFMT) == S_IFSOCK)

É assim que st_mode obtém esses valores S_IFDIR e S_IFREG .

Apenas FYI ... Agora, para uma pergunta principal sobre como os inodes identificam o tipo de arquivo é:

Para o sistema de arquivos XFS, uma estrutura de dados inode é dividida em 3 partes:

  • di_core (96 bytes)
  • di_u data fork
  • di_a atributo estendido garfo

O núcleo contém o que o inode representa, os dados estatísticos e as informações que descrevem os dados e os forks de atributos. Aqui o tipo de arquivo é controlado por di_core.di_mode (por exemplo, arquivo regular, diretório, link, etc).

A bifurcação de dados di_u "contém dados normais relacionados ao inode.

O fork do atributo di_a "contém atributos estendidos.

    
por 24.12.2016 / 04:11