简体   繁体   中英

Getting the name of the last mounted/unmounted filesystem

I know I can monitor (using poll , or select ) on the files /proc/mount or /etc/mtab and findout WHEN a filesystem is mounted or unmounted. Also I can use getmntent for getting a list of mounted filesystems.

My app is intended to monitor the mounted filesystem and report any change (mount or unmount).

My solution:

  1. Detect some change in /proc/mounts .
  2. Get all currently mounted filesystem with getmntent .
  3. Compare the obtained list with some previous list.
  4. Process the difference.

But I need to know if there are some way to get the last filesystem mounted when polling from /proc/mounts or /etc/mtab . Just reading the file or polling data into some structure (like mntent for instance.)

Solution description

The implemented solution involve udev , poll , setmntent and getmntent .

The idea is to keep a list of all the mounted file systems (this is not memory-expensive, since the number of devices is generally low) and the list has to be created only once.

Using poll() over "/proc/mounts" you can find out when a filesystem is mounted or unmounted. And then using udev you can get the list of devices mounted at that time. So you can compare with the list you already have and that way you will know if the filesystem was mounted or unmounted and which filesystem is the affected.

Relevant code samples of the soultion

Function to get the mounted nodes.

vector<string> get_mounted_storage_nodes()
{
    vector<string> storage_nodes = get_storage_nodes(); // This uses udev.
    vector<string> mounted_nodes;
    struct mntent *mntent;

    FILE *file;
    file = setmntent("/etc/mtab", "r");

    while ((mntent = getmntent(file)))
    {
        string mounted_node(mntent->mnt_fsname);
        vector<string>::iterator it;
        it = find(storage_nodes.begin(), storage_nodes.end(), mounted_node);
        if (it != storage_nodes.end())
            mounted_nodes.push_back(mounted_node);
    }

    return mounted_nodes;
}

Finding out if the filesystem was mounted or unmounted

Simple just compare the size of both lits.

// event is a convenience struct that holds the name of the affected
// filesystem and the action (mounted or unmounted).

vector<string> new_mounted_nodes = get_mounted_storage_nodes();
int new_size = new_mounted_nodes.size();
int curr_size = mounted_nodes.size();

if (new_size == curr_size)
    event.action = NONE;    // No partition was mount or unmounted.
                            // This case is very common when the poll
                            // is working as non-blocking because the timeout.
else
    event.action = new_size > curr_size ? MOUNT : UMOUNT;

Finding out if the affected filesystem

vector<string> new_mounted_nodes = get_mounted_storage_nodes();

Using the previous line, if the filesystem was mounted, you only have to find the element of new_mounted nodes that is not in the list of mounted nodes you already have. On the other hand, if the filesystem was unmounted you have to find the element that is in the list you already have but not in new_mounted_nodes .

Code sample:

switch(event.action)
{
    case MOUNT:

        for (auto it = new_mounted_nodes.begin(); it != new_mounted_nodes.end(); ++it)
            if (find(mounted_nodes.begin(), mounted_nodes.end(), *it) == mounted_nodes.end())
            {
                event.node = *it;
                break;
            }
        break;

    case UMOUNT:
        for (auto it = mounted_nodes.begin(); it != mounted_nodes.end(); ++it)
            if (find(new_mounted_nodes.begin(), new_mounted_nodes.end(), *it) == new_mounted_nodes.end())
            {
                event.node = *it;
                break;
            }
        break;
    default:
        break;
}

IMPORTANT NOTE: The complexity of the latest code is O(n^2) , but the number of mounted devices will generally (I don't want to be absolute) be lower that 20. So, the algorithm will run very fast.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM