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?