#c #linux
#c #linux
Вопрос:
В настоящее время я работаю над программой, которая должна отображать информацию о смонтированном флэш-диске. Я хочу отобразить полное пространство, свободное пространство, тип файловой системы и имя тома. Но проблема в том, что я не могу найти никакого API, через который я мог бы получить имя тома (volume label). Есть ли какой-либо API для этого?
p.s. полное пространство, свободное пространство и тип файловой системы я получаю с помощью statfs
функции
Ответ №1:
Предполагая, что вы работаете на последнем настольном дистрибутиве (Fedora, Ubuntu и т.д.), у вас запущен демон HAL и сеанс D-Bus.
В org.freedesktop.UDisks
пространстве имен вы можете найти объект, представляющий этот диск (скажем org/freedekstop/UDisks/devices/sdb/
. Он реализует org.freedesktop.UDisks.interface
. Этот интерфейс обладает всеми свойствами, о которых вы только можете мечтать, включая UUID ( IdUuid
), FAT label ( IdLabel
), все сведения о файловой системе, SMART status (если диск это поддерживает) и т.д. и т.п.
Как использовать D-Bus API на C — тема для другого вопроса. Я предполагаю, что это уже подробно обсуждалось — просто найдите теги [dbus] и [c].
Ответ №2:
Флэш-накопители обычно имеют формат FAT32, что означает, что «имя», которое вы ищете, вероятно, является меткой диска FAT. Наиболее распространенная команда Linux для извлечения этой информации — mlabel
из пакета mtools.
Команда выглядит следующим образом:
[root@localhost]$ mlabel -i /dev/sde1 -s ::
Volume label is USB-DISK
Эта программа работает, считывая заголовок raw FAT файловой системы и извлекая метку из этих данных. Вы можете посмотреть исходный код приложения, чтобы увидеть, как вы можете повторить синтаксический анализ данных FAT в своем собственном приложении… или вы можете просто выполнить mlabel
двоичный файл и прочитать результат в своей программе. Последнее для меня звучит проще.
Комментарии:
1. e2label /dev/sda2 для ext. Однако это не ответ на этот вопрос. OP пометил вопрос символом C.
2.@Basilevs: Вы можете сделать это на C:
pipe();
fork();
exec();
3. Выполняется ли следующее программирование на C? system («python arbitrary_python_script.py «)
4. @Basilevs: ОК, умник. Вот ваши варианты: Вы можете либо прочитать необработанный диск, вручную проанализировать структуру файловой системы и извлечь метку. Или вы можете использовать существующую программу, написанную именно для этого. Для этого нет разделяемой библиотеки, но есть исполняемый файл. Итак, независимо от того, пишете ли вы на C, python, haskell или INTERCAL, вы делаете это одинаково. Запустите существующую программу и проанализируйте выходные данные.
5. Большинство программ Linux используют соответствующие библиотеки, а не исполняемые файлы. В конце концов, процесс создания сложен… Вероятно, эту задачу следует выполнять путем извлечения информации из /sys или /proc, а не путем чтения необработанного диска. Я не знаю, как инициировать процедуры обнаружения на уровне ядра, но полагаю, что hald не запускает отдельный процесс для этого.
Ответ №3:
Для вызова методов:
kernResult = self->FindEjectableCDMedia(amp;mediaIterator);
if (KERN_SUCCESS != kernResult) {
printf("FindEjectableCDMedia returned 0xxn", kernResult);
}
kernResult = self->GetPath(mediaIterator, bsdPath, sizeof(bsdPath));
if (KERN_SUCCESS != kernResult) {
printf("GetPath returned 0xxn", kernResult);
}
и методы:
// Returns an iterator across all DVD media (class IODVDMedia). Caller is responsible for releasing
// the iterator when iteration is complete.
kern_return_t ScanPstEs::FindEjectableCDMedia(io_iterator_t *mediaIterator)
{
kern_return_t kernResu<
CFMutableDictionaryRef classesToMatch;
// CD media are instances of class kIODVDMediaTypeROM
classesToMatch = IOServiceMatching(kIODVDMediaClass);
if (classesToMatch == NULL) {
printf("IOServiceMatching returned a NULL dictionary.n");
} else {
CFDictionarySetValue(classesToMatch, CFSTR(kIODVDMediaClass), kCFBooleanTrue);
}
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
return kernResu<
}
// Given an iterator across a set of CD media, return the BSD path to the
// next one. If no CD media was found the path name is set to an empty string.
kern_return_t GetPath(io_iterator_t mediaIterator, char *Path, CFIndex maxPathSize)
{
io_object_t nextMedia;
kern_return_t kernResult = KERN_FAILURE;
DADiskRef disk = NULL;
DASessionRef session = NULL;
CFDictionaryRef props = NULL;
char * bsdPath = '';
*Path = '';
nextMedia = IOIteratorNext(mediaIterator);
if (nextMedia) {
CFTypeRef bsdPathAsCFString;
bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,CFSTR(kIOBSDNameKey),kCFAllocatorDefault,0);
if (bsdPathAsCFString) {
//strlcpy(bsdPath, _PATH_DEV, maxPathSize);
// Add "r" before the BSD node name from the I/O Registry to specify the raw disk
// node. The raw disk nodes receive I/O requests directly and do not go through
// the buffer cache.
//strlcat(bsdPath, "r", maxPathSize);
size_t devPathLength = strlen(bsdPath);
if (CFStringGetCString( (CFStringRef)bsdPathAsCFString , bsdPath devPathLength,maxPathSize - devPathLength, kCFStringEncodingUTF8)) {
qDebug("BSD path: %sn", bsdPath);
kernResult = KERN_SUCCESS;
}
session = DASessionCreate(kCFAllocatorDefault);
if(session == NULL) {
qDebug("Can't connect to DiskArbn");
return -1;
}
disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, bsdPath);
if(disk == NULL) {
CFRelease(session);
qDebug( "Can't create DADisk for %sn", bsdPath);
return -1;
}
props = DADiskCopyDescription(disk);
if(props == NULL) {
CFRelease(session);
CFRelease(disk);
qDebug("Can't get properties for %sn",bsdPath);
return -1;
}
CFStringRef daName = (CFStringRef )CFDictionaryGetValue(props, kDADiskDescriptionVolumeNameKey);
CFStringGetCString(daName,Path,sizeof(Path),kCFStringEncodingUTF8);
if(daName) {
qDebug("%s",Path);
CFRetain(daName);
}
CFRelease(daName);
CFRelease(props);
CFRelease(disk);
CFRelease(session);
CFRelease(bsdPathAsCFString);
}
IOObjectRelease(nextMedia);
}
return kernResu<
}
Комментарии:
1. Разве этот код не для BSD / OSX? И разве это не применимо только к CD / DVD?