Eu escrevi uma função que retorna 1
se o argumento for o dispositivo raiz,
0
se não for e um valor negativo para erro:
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> static int root_check(const char *disk_dev) { static const char root_dir[] = "/"; struct stat root_statb; struct stat dev_statb; if (stat(root_dir, &root_statb) != 0) { perror(root_dir); return -1; } if (!S_ISDIR(root_statb.st_mode)) { fprintf(stderr, "Error: %s is not a directory!\n", root_dir); return -2; } if (root_statb.st_ino <= 0) { fprintf(stderr, "Warning: %s inode number is %d; " "unlikely to be valid.\n", root_dir, root_statb.st_ino); } else if (root_statb.st_ino > 2) { fprintf(stderr, "Warning: %s inode number is %d; " "probably not a root inode.\n", root_dir, root_statb.st_ino); } if (stat(disk_dev, &dev_statb) != 0) { perror(disk_dev); return -1; } if (S_ISBLK(dev_statb.st_mode)) /* That's good. */ ; else if (S_ISCHR(dev_statb.st_mode)) { fprintf(stderr, "Warning: %s is a character-special device; " "might not be a disk.\n", disk_dev); } else { fprintf(stderr, "Warning: %s is not a device.\n", disk_dev); return(0); } if (dev_statb.st_rdev == root_statb.st_dev) { printf("It looks like %s is the root file system (%s).\n", disk_dev, root_dir); return(1); } // else printf("(It looks like %s is NOT the root file system.)\n", disk_dev); return(0); }
Os dois primeiros testes são basicamente verificações de sanidade: se stat("/", …)
falhar ou " /
" não for um diretório, seu sistema de arquivos está quebrado. Os testes st_ino
são uma espécie de tiro no escuro. AFAIK, números de inodes nunca devem ser negativos ou nulos. Historicamente (pelo que me refiro a 30 anos atrás), o diretório-raiz sempre teve o inode número 1. Isso ainda pode ser verdade para alguns tipos de * nix (alguém ouviu falar de “Minix”?), E pode ser verdade para o especial sistemas de arquivos, como /proc
, e para sistemas de arquivos Windows (FAT), mas a maioria dos sistemas Unix e Unix-like contemporâneos parecem usar o inode número 1 para rastrear blocos ruins, empurrando a raiz para o inode número 2.
S_ISBLK
é verdadeiro para "dispositivos de bloco", como /dev/sda1
, em que a saída de ls -l
começa com " b
". Da mesma forma, S_ISCHR
é verdadeiro para "dispositivos de caractere", em que a saída de ls -l
começa com " c
". (Você pode ocasionalmente ver nomes de disco como /dev/rsda1
; o " r
" significa "raw". Dispositivos de disco brutos às vezes são usados para fsck
e backup, mas não para montagem.) Todo inode tem st_dev
, que diz em qual sistema de arquivos esse inode está. Os inodes para dispositivos também têm st_rdev
campos, que dizem quais dispositivos eles são . (Os dois números separados por vírgulas que você vê no lugar do tamanho do arquivo quando você ls -l
um dispositivo são os dois bytes de st_rdev
.)
Assim, o truque é ver se o st_rdev
do dispositivo de disco corresponde ao st_dev
do diretório raiz; ou seja, o dispositivo especificado é aquele em que “ /
” está ativado?