Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Список томов/разделов/смонтированных устройств


Автор: andrew_121 6.6.2009, 16:15
Здравствуйте!
Подскажите. Как получить этот список? Кроме как парсить /etc/fstab.

Автор: MAKCim 6.6.2009, 16:36
andrew_121, 
сделай
strace -f df 2>log
и увидишь, что парсится /etc/mtab

Автор: Pointer 6.6.2009, 16:42
Парсить вывод команды mount без параметров.
Или заглянуть в файлы fstab.h, mount.h.

Автор: MAKCim 6.6.2009, 17:53
Цитата(Pointer @  6.6.2009,  16:42 Найти цитируемый пост)
Парсить вывод команды mount без параметров.


Цитата(MAKCim @  6.6.2009,  16:36 Найти цитируемый пост)
и увидишь, что парсится /etc/mtab 


Автор: andrew_121 6.6.2009, 19:38
Понятно.

Всем спасибо!

Автор: andrew_121 6.6.2009, 20:52
Значит вот что у меня есть.

/etc/fstab
Код

# <file system>                           <mount point>  <type>      <options>                         <dump>  <pass>
####################################################################################################################
proc                                      /proc           proc       defaults                            0       0
UUID=9a450207-011f-4c2f-9f6f-ad47f53173ee /               reiserfs   notail,relatime                     0       1
UUID=AEC8893FC88906B5                     /media/c        ntfs       defaults,nls=utf8,umask=007,gid=46  0       1
/dev/sda5                                 /media/d        ntfs       defaults,nls=utf8,umask=007,gid=46  0       1
/dev/sda7                                 none            swap       sw                                  0       0
/dev/scd0                                 /media/cdrom0   udf,iso9660 user,noauto,exec,utf8              0       0


/etc/mtab
Код

/dev/sda6 / reiserfs rw,relatime,notail 0 0
tmpfs /lib/init/rw tmpfs rw,nosuid,mode=0755 0 0
proc /proc proc rw,noexec,nosuid,nodev 0 0
sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0
varrun /var/run tmpfs rw,nosuid,mode=0755 0 0
varlock /var/lock tmpfs rw,noexec,nosuid,nodev,mode=1777 0 0
udev /dev tmpfs rw,mode=0755 0 0
tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0
devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=620 0 0
fusectl /sys/fs/fuse/connections fusectl rw 0 0
lrm /lib/modules/2.6.28-11-generic/volatile tmpfs rw,mode=755 0 0
/dev/sda1 /media/c fuseblk rw,nosuid,nodev,allow_other,default_permissions,blksize=4096 0 0
securityfs /sys/kernel/security securityfs rw 0 0
/dev/sda5 /media/d fuseblk rw,nosuid,nodev,allow_other,default_permissions,blksize=4096 0 0
/dev/sr0 /media/cdrom0 iso9660 ro,nosuid,nodev,utf8 0 0


Любопытен следующий момент. Как по UUID определить что за устройство?
Надо посмотреть исходники df.

Автор: andrew_121 6.6.2009, 21:24
Посмотрел smile  Проще самому написать smile 
Вот только как быть с UUID? Может кто знает?

Автор: andrew_121 7.6.2009, 01:13
Значит партиции могут зваться /dev/hd** или /dev/sd**. Это все? Или еще как-то?
CD-приводы, /dev/sc** или /dev/sr*. С последним не понятно. Проясните плиз.

Автор: Pointer 7.6.2009, 09:34
Цитата

Любопытен следующий момент. Как по UUID определить что за устройство?


Можно с blkid, примерно такой вывод.

Код

/dev/hda1: UUID="1e68b38a-2001-4946-9e6c-0eec1040b71f" TYPE="ext3"
/dev/hda5: TYPE="swap"
/dev/hda6: UUID="d18952ac-29a8-4fbb-b0f4-e4c1e73895ab" TYPE="reiserfs"
/dev/hdb1: UUID="d5d55cdb-25d6-4dbf-baa8-436e327c2d2b" TYPE="ext3"

Автор: MAKCim 7.6.2009, 10:13
Цитата(andrew_121 @  7.6.2009,  01:13 Найти цитируемый пост)
Значит партиции могут зваться /dev/hd** или /dev/sd**. Это все? Или еще как-то?
CD-приводы, /dev/sc** или /dev/sr*. С последним не понятно. Проясните плиз. 

как угодно если стоИт udev


Автор: andrew_121 7.6.2009, 10:24
Цитата(MAKCim @  7.6.2009,  10:13 Найти цитируемый пост)
как угодно если стоИт udev

А их что, программа именует? Или юзер со злым умыслом?

Автор: MAKCim 7.6.2009, 10:37
Цитата(andrew_121 @  7.6.2009,  10:24 Найти цитируемый пост)
А их что, программа именует? Или юзер со злым умыслом? 

по настройкам злого юзера программа smile

Автор: andrew_121 7.6.2009, 10:56
Цитата(MAKCim @  7.6.2009,  10:37 Найти цитируемый пост)
по настройкам злого юзера программа

Ну допустим что таких мало. Я к примеру этим не занимаюсь. Это система как-то там настраивает smile 

Вот еще вопрос. По колонке type в /etc/fstab можно определить тип устройства, по типу ФС, так? Если да, то осталось найти список ФС поддерживаемых Линукс. И еще вопрос. А cd-rom бывают иного типа кроме iso9660?

Автор: andrew_121 7.6.2009, 11:16
Может кто-то знает где есть хидер со списком ФС?

Автор: MAKCim 7.6.2009, 11:20
Цитата(andrew_121 @  7.6.2009,  10:56 Найти цитируемый пост)
А cd-rom бывают иного типа кроме iso9660? 

естественно

Цитата(andrew_121 @  7.6.2009,  10:56 Найти цитируемый пост)
По колонке type в /etc/fstab можно определить тип устройства, по типу ФС, так?

нет

мы можем узнать MAJOR номер файла устройства
а вот по MAJOR номеру можем узнать тип устройства

Добавлено через 33 секунды
Цитата(andrew_121 @  7.6.2009,  11:16 Найти цитируемый пост)
Может кто-то знает где есть хидер со списком ФС?

список всех зарегистрированных драйверов ФС
/proc/filesystems

Автор: andrew_121 7.6.2009, 11:39
Нашел. Вот разделил их по категориям. Просьба поправить меня, если какой-то тип ФС не в нужной ему категории.
Код

static const char* hd_fs[] = {
    "adfs",
    "affs",
    "autofs",
    "befs",
    "bfs",
    "binfmt_misc",
    "coda",
    "coh",
    "cramfs",
    "devfs",
    "devpts",
    "efs",
    "ext",
    "ext2/ext3",
    "ext2",
    "fat",
    "fusectl",
    "hpfs",
    "hugetlbfs",
    "jffs2",
    "jffs",
    "jfs",
    "lustre",
    "minix",
    "minix (30 char.)",
    "minix v2",
    "minix v2 (30 char.)",
    "msdos",
    "novell",
    "nfs",
    "nfsd",
    "ntfs",
    "openprom",
    "proc",
    "qnx4",
    "ramfs",
    "reiserfs",
    "romfs",
    "smb",
    "squashfs",
    "sysfs",
    "sysv2",
    "sysv4",
    "tmpfs",
    "ufs",
    "vfat"
    "vxfs",
    "xenix",
    "xfs",
    "xia"
};

static const char* cd_fs[] = {
    "iso9660",
    "isofs",
    "udf"
};

static const char* usb_fs[] = {
    "usbdevfs"
};



Добавлено @ 11:42
Цитата(MAKCim @  7.6.2009,  11:20 Найти цитируемый пост)
естественно

Ну подскажи smile 


Цитата(MAKCim @  7.6.2009,  11:20 Найти цитируемый пост)
мы можем узнать MAJOR номер файла устройства
а вот по MAJOR номеру можем узнать тип устройства

А это как? smile

Автор: MAKCim 7.6.2009, 13:07
andrew_121, 
как можно сопоставлять файловой системе тип устройства?
я могу iso образ к примеру прикрутить через loop или на instance ramfs

Цитата(andrew_121 @  7.6.2009,  11:39 Найти цитируемый пост)
Ну подскажи

что?

Цитата(andrew_121 @  7.6.2009,  11:39 Найти цитируемый пост)
А это как?

берем первую строку из /etc/mtab и делаем stat
по st_dev находим MAJOR номер и сравниваем с linux/major.h

Автор: andrew_121 7.6.2009, 13:40
Цитата(MAKCim @  7.6.2009,  13:07 Найти цитируемый пост)
я могу iso образ к примеру прикрутить через loop или на instance ramfs

Да. Но стандартный юзер этого делать не станет smile 


Цитата(MAKCim @  7.6.2009,  13:07 Найти цитируемый пост)
берем первую строку из /etc/mtab и делаем stat
по st_dev находим MAJOR номер и сравниваем с linux/major.h

Это понятно. Но хочется без вызовов системных функций.

Кароче вот что у меня получилось. Жду критики/исправлений/дополнений.
Код

#include <fstream>
#include <cctype>
#include <string>
#include <vector>
#include <algorithm>

static const char* hd_fs[] = {
    "adfs",
    "affs",
    "autofs",
    "befs",
    "bfs",
    "binfmt_misc",
    "coda",
    "coh",
    "cramfs",
    "devfs",
    "devpts",
    "efs",
    "ext",
    "ext2/ext3",
    "ext2",
    "fat",
    "fusectl",
    "fuseblk",
    "hpfs",
    "hugetlbfs",
    "jffs2",
    "jffs",
    "jfs",
    "lustre",
    "minix",
    "minix (30 char.)",
    "minix v2",
    "minix v2 (30 char.)",
    "msdos",
    "novell",
    "nfs",
    "nfsd",
    "ntfs",
    "openprom",
    "proc",
    "qnx4",
    "ramfs",
    "reiserfs",
    "romfs",
    "smb",
    "squashfs",
    "sysfs",
    "sysv2",
    "sysv4",
    "tmpfs",
    "ufs",
    "vfat"
    "vxfs",
    "xenix",
    "xfs",
    "xia"
};

static const char* cd_fs[] = {
    "iso9660",
    "isofs",
    "udf"
};

static const char* usb_fs[] = {
    "usbdevfs"
};

/***************************************************************************/

template <class InputIterator, class OutputIterator, class Predicate>
OutputIterator copy_if(    InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                Predicate pred
                            )
{
    InputIterator currentIn = first;
    OutputIterator currentOut = result;
    while (currentIn != last) {
        if (pred(*currentIn)) {
            *currentOut = *currentIn;
            ++currentOut;
            ++currentIn;
        } else {
            ++currentIn;
        }
    }
    
    return currentOut;
}

/***************************************************************************/

struct Drive {
    typedef enum _d_type {hdd, usb, cdrom} d_type;
    /**/
    Drive() {}
    Drive(const Drive& d) {
        device = d.device;
        mpoint = d.mpoint;
        type = d.type;
    }
    void reset() {
        device.clear();
        mpoint.clear();
    }
    std::string device;
    std::string mpoint;
    d_type type;
};

typedef std::vector<Drive> DriveList;

/***************************************************************************/

bool is_ignored_predicate(std::string::value_type v) {
    return (v != ' ' && v != '\t');
}

bool is_not_ignored_predicate(std::string::value_type v) {
    return !is_ignored_predicate(v);
}

/***************************************************************************/

bool parse_string(Drive* d, std::string& s) {
    if ( !(s.substr(0, 5) == "/dev/") ) return false;
    
    std::string type;
    std::string::iterator it1;
    std::string::iterator it2;
    
    it1 = s.begin();
    it2 = std::find_if(it1, s.end(), is_not_ignored_predicate);
    d->device.resize(it2-it1);
    std::copy(it1, it2, d->device.begin());
    
    it1 = std::find_if(it2, s.end(), is_ignored_predicate);
    it2 = std::find_if(it1, s.end(), is_not_ignored_predicate);
    d->mpoint.resize(it2-it1);
    std::copy(it1, it2, d->mpoint.begin());
    
    it1 = std::find_if(it2, s.end(), is_ignored_predicate);
    it2 = std::find_if(it1, s.end(), is_not_ignored_predicate);
    type.resize(it2-it1);
    std::copy(it1, it2, type.begin());

    /* HDD */    
    for ( const char** p = &hd_fs[0]; *p != hd_fs[sizeof(hd_fs)/sizeof(hd_fs[0])]; p++ ) {
        if ( type == *p ) {
            d->type = Drive::hdd;
            return true;
        }
    }
    /* USB */    
    for ( const char** p = &usb_fs[0]; *p != usb_fs[sizeof(usb_fs)/sizeof(usb_fs[0])]; p++ ) {
        if ( type == *p ) {
            d->type = Drive::usb;
            return true;
        }
    }
    /* CD-ROM*/    
    for ( const char** p = &cd_fs[0]; *p != cd_fs[sizeof(cd_fs)/sizeof(cd_fs[0])]; p++ ) {
        if ( type == *p ) {
            d->type = Drive::cdrom;
            return true;
        }
    }
    
    return false;
}

/***************************************************************************/

DriveList get_all_drives() {
    const char* fname = "/etc/mtab";
    std::string buf;
    Drive drive;
    DriveList list;
    
    std::ifstream in(fname);
    if ( !in ) { return list; }
    
    while ( !in.eof() ) {
        std::getline(in, buf, '\n');
        if ( buf.length() < 5 ) continue;

        std::copy(std::find_if(buf.begin(), buf.end(), is_ignored_predicate),
                    buf.end(),
                    buf.begin()
                    );

        if ( buf[0] == '#' ) continue;
        
        if ( parse_string(&drive, buf) ) {
            list.push_back(drive);
        }
        drive.reset();
    }
    
    return list;
}

/***************************************************************************/

template<Drive::d_type T> bool is_required_drive_type(const Drive& d) {
    return d.type == T;
}

template<Drive::d_type T> DriveList get_drives() {
    DriveList list = get_all_drives();
    DriveList::iterator it;
    it = copy_if(list.begin(), list.end(), list.begin(), is_required_drive_type<T>);
    list.resize(it-list.begin());
    
    return list;
}

/***************************************************************************/

int main(int argc, char** argv) {

    DriveList h = get_drives<Drive::hdd>();
    DriveList u = get_drives<Drive::usb>();
    DriveList c = get_drives<Drive::cdrom>();

    return 0;
}

/***************************************************************************/


Автор: MAKCim 7.6.2009, 14:17
Цитата(andrew_121 @  7.6.2009,  13:40 Найти цитируемый пост)
Да. Но стандартный юзер этого делать не станет

это очень плохая аргументация
недетерминированность - это плохо


Цитата(andrew_121 @  7.6.2009,  13:40 Найти цитируемый пост)
Это понятно. Но хочется без вызовов системных функций.

ага
хочется мороженного без молока
open считается системной функцией? ;)


Цитата(andrew_121 @  7.6.2009,  13:40 Найти цитируемый пост)
Жду критики/исправлений/дополнений.

1. C++
2. 
Код

#!/usr/bin/python
import re
import sys
fs_types = {"hd_fs": (), "cd_fs": (), "usb_fs": ()}
filter(lambda x: x != False, map(lambda s: re.split("\s+", s)[2] in fs_types[sys.argv[1]] and s[:s.find(" ")], open("/etc/mtab")))

к вопросу о краткости
3. замечание об универсальности

Автор: andrew_121 7.6.2009, 14:37
Цитата(MAKCim @  7.6.2009,  14:17 Найти цитируемый пост)
это очень плохая аргументация
недетерминированность - это плохо

Согласен. Буду править.



Цитата(MAKCim @  7.6.2009,  14:17 Найти цитируемый пост)
1. C++

Согласен. Но мне для проги написанной на Кут.  smile 



Цитата(MAKCim @  7.6.2009,  14:17 Найти цитируемый пост)
3. замечание об универсальности

Не понял...?

Автор: MAKCim 7.6.2009, 16:36
Цитата(andrew_121 @  7.6.2009,  14:37 Найти цитируемый пост)
Не понял...? 


Цитата(andrew_121 @  7.6.2009,  13:40 Найти цитируемый пост)
Да. Но стандартный юзер этого делать не станет

в этом неуниверсальность

Автор: andrew_121 7.6.2009, 16:43
Ааа...
Буду развивать...

Автор: _GRIN_ 3.7.2009, 14:34
andrew_121, если на твоей машине есть демоны udev, dbus и hal (как полагаю на 95% nix* систем), то я советую посмотреть в сторону  hal-a. Всё делаю через него, включая различные уведомления об измененеии какого-либо параметра интересующего меня железа. Ссылочка на спецификацию: http://people.freedesktop.org/~david/hal-spec/hal-spec.html

Автор: andrew_121 4.7.2009, 10:26
_GRIN_, Дело в том, что сей код, был так задуман.
За ссылочку спасибо. Попрасвещаюсь.

Автор: Cheloveck 8.7.2009, 19:26
По чистой случайности сейчас занимался тем же самым. Вот пример использования HAL
Код

extern "C" {
#include <dbus/dbus.h>
#include <libhal.h>
#include <libhal-storage.h>
}

#include <iostream>

int main(int argc, char *argv[])
{
    (void)argc; // unused parametr.
    (void)argv; // unused parametr.

    DBusError error;
    DBusConnection *connection;
    LibHalContext *context;

    dbus_error_init( &error );

    connection = dbus_bus_get( DBUS_BUS_SYSTEM, &error );
    if( !connection )
    {
        std::cerr << "Error dbus_bus_get: " << error.name << ": " <<
            error.message << std::endl;
        dbus_error_free( &error );
        return 1;
    }

    context = libhal_ctx_new();
    if( !context )
    {
        std::cerr << "Error: can not create LibHalContext\n";
        dbus_error_free( &error );
        return 2;
    }

    if( !libhal_ctx_set_dbus_connection( context, connection ) )
    {
        std::cerr << "Error: can not set dbus connection\n";
        dbus_error_free( &error );
        libhal_ctx_free( context );
        return 3;
    }

    if( !libhal_ctx_init( context, &error ) )
    {
        std::cerr << "Error: can not init libhal\n";
        dbus_error_free( &error );
        libhal_ctx_free( context );
        dbus_connection_unref( connection );
    }

    char **devices;
    char **volumes;
    int num_devices;
    int num_volumes;
    LibHalDrive *drive;
    LibHalVolume *volume;

    devices = libhal_get_all_devices( context, &num_devices, &error );

    for( int i = 0; i < num_devices; i++ )
    {
        drive = libhal_drive_from_udi( context, devices[i] );
        if( !drive )
            continue;

        const char * device_file = libhal_drive_get_device_file( drive );
        if( device_file )
            std::cout << "Drive: " <<  device_file<< std::endl;

        std::cout << "Size: " << libhal_drive_get_size( drive ) <<
            std::endl;

        const char * scheme = libhal_drive_get_partition_scheme( drive );
        if( scheme )
            std::cout << "Partition scheme: " << scheme << std::endl;

        volumes = libhal_drive_find_all_volumes( context, drive, &num_volumes );
        if( volumes )
        {
            for( int j = 0; j < num_volumes; j++ )
            {
                volume = libhal_volume_from_udi( context, volumes[j] );
                if( !volume )
                    continue;

                const char * volume_device_file =
                    libhal_volume_get_device_file( volume );
                if( volume_device_file )
                    std::cout << "Volume: " << volume_device_file << std::endl;

                const char * mount_point =
                    libhal_volume_get_mount_point( volume );
                if( mount_point )
                std::cout << "Mount point: " << mount_point << std::endl;

                std::cout << std::endl;
            }
            libhal_free_string_array( volumes );
        }

        libhal_drive_free( drive );
        std::cout << "-----------------------\n\n";
    }

    libhal_free_string_array( devices );
    libhal_ctx_shutdown( context, &error );
    dbus_connection_unref( connection );
    libhal_ctx_free( context );
    dbus_error_free( &error );


    return 0;
}


Это я тут сам разбирался, поэтому не всё красиво, но работает правильно!
У меня показывает так
Код

Drive: /dev/sde
Size: 0
-----------------------

Drive: /dev/sdd
Size: 0
-----------------------

Drive: /dev/sdc
Size: 0
-----------------------

Drive: /dev/sdf
Size: 0
-----------------------

Drive: /dev/scd0
Size: 0
-----------------------

Drive: /dev/sdb
Size: 500106780160
Partition scheme: mbr
Volume: /dev/sdb1
Mount point: /home/sergey/server

-----------------------

Drive: /dev/sda
Size: 500106780160
Partition scheme: mbr
Volume: /dev/sda7
Mount point: /home/sergey/docs

Volume: /dev/sda6
Mount point: /home

Volume: /dev/sda5

Volume: /dev/sda2

Volume: /dev/sda1
Mount point: /

-----------------------

Drive: /dev/fd0
Size: 0
-----------------------


Там можно получить аналогичным способом любую информацию о дисках, разделах... да собственно обо всех устройствах.

Автор: andrew_121 9.7.2009, 00:52
Cheloveck, Это понятно. Но сей код мне нужен для пользовательской программы написанной на Qt. Нет смысла привязывать ее к Hal.

Автор: Cheloveck 9.7.2009, 11:34
andrew_121, моя программа тоже на Qt, но к HAL я всё же решил привязать, ибо удобно))

Автор: andrew_121 9.7.2009, 17:54
Cheloveck, Идеология Qt - кроссплатформенность! Hal ее нарушает.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)