Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need to write a program that receives a block device as input, like /dev/sda1, and has to perform a set of operations depending on if the filesystem inside are currently running or not.

We'll assume the input will always has a correct linux directory tree, the only I need to know is if there's a particular directory structure or file/s that can reliably determine whether the system inside is running. I mean whether the filesystem contains the root of a system that is powered on.

It should work for any filesystem or linux kernel version.

Thanks!

share|improve this question
3  
When you say 'up/down' do you mean 'mounted/unmounted'? –  Herman Torjussen Jan 12 '13 at 21:20
    
How about raw devices for VM guests or DB application? –  dchirikov Jan 12 '13 at 21:25
    
Could you explain better what you mean? From what I understood, a filesystem "up" is mounted and "down" unmounted. But if you have it under the control of the LVM then you need to check if it is part of the LVM or as a raw device to some database you also need to check if it is being used by the database as in this last case it will look as if it is not mounted but in fact is being used but your DB. –  BitsOfNix Jan 13 '13 at 6:48
    
@htor & @AlexandreAlves, I've chosen the wrong words, what I meant with "up/down" were not "mounted/unmounted", but whether is the filesystem contains the root of a running system instead. For example, you can have two disks with a linux inside each one in the same computer, for example one with ubuntu and the other with debian; but it only can be running one at once. If you look inside the /proc/ folder it will be more or less populated depending on if it's running right now or not. That's what I meant. –  JLledo Jan 13 '13 at 16:26
    
When you clarify your question, please do it by editing the question and not by commenting. … // … Do you know what kind of filesystem it is (e.g., ext, ntfs, etc.)? The answer to your question may depend on the answer to this question. –  Scott Jan 13 '13 at 23:25

2 Answers 2

up vote 0 down vote accepted

I’ve written a function that returns 1 if the argument is the root device, 0 if it is not, and a negative value for error:

#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);
}

The first two tests are basically sanity checks: if stat("/", …) fails or “/” is not a directory, your filesystem is broken.  The st_ino tests are something of a shot in the dark. AFAIK, inode numbers should never be negative or zero.  Historically (by which I mean 30 years ago), the root directory always had inode number 1.  This may still be true for a few flavors of *nix (anybody heard of “Minix”?), and it may be true for the special filesystems, like /proc, and for Windows (FAT) filesystems, but most contemporary Unix and Unix-like systems seem to use inode number 1 for tracking bad blocks, pushing the root up to inode number 2.

S_ISBLK is true for “block devices”, like /dev/sda1, where the output from ls -l begins with “b”.  Likewise, S_ISCHR is true for “character devices”, where the output from ls -l begins with “c”.  (You may occasionally see disk names like /dev/rsda1; the “r” stands for “raw”.  Raw disk devices are sometimes used for fsck and backup, but not mounting.)  Every inode has a st_dev, which says what filesystem that inode is on.  Inodes for devices also have st_rdev fields, which say what device they are.  (The two comma-separated numbers you see in place of the file size when you ls -l a device are the two bytes of st_rdev.)

So, the trick is to see whether the st_rdev of the disk device matches the st_dev of the root directory; i.e., is the specified device the one that “/” is on?

share|improve this answer
    
The question was whether the filesystem is mounted, not whether it is mounted as the root directory. –  psusi Apr 19 '13 at 22:28
    
@psusi: On Jan 14 at 18:23 JLledo issued this comment: «the first option, "the filesystem is the root of the current system –– the one that your program is running on".» –  Scott Apr 19 '13 at 23:30
    
Hi!! I've tested it and actually works!! thank you so much!! I was wrongly looking for some file or directory that could give me that information, but I didn't think of using stat functions. This is the best solution. –  JLledo Apr 20 '13 at 23:03
    
I’m glad I could help. –  Scott Apr 20 '13 at 23:57

You can check whether the device is mounted, and where:

awk -v device=/dev/sda1 ' $1 == device {print $2}' /proc/mounts

This doesn't detect devices used by a kernel subsystem such as mdraid or LVM. These are visible through /sys/class/block/sda1/holders (that directory contains a symlink to the device mapper item that uses the device).

share|improve this answer
    
Thanks! but what I need to know isn't only whether the filesystem is mounted, but also whether it's a root directory and is running right now (powered on). My mistake! I've edited the question... –  JLledo Jan 14 '13 at 11:07
    
@JLledo I'm not sure I understand the question. Are you trying to find out whether that filesystem is mounted on /? Does it count if it's mounted in a VM? Does it count if the last time anything happened to it, it was mounted at /, but then the system crashed? –  Gilles Jan 14 '13 at 22:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.