How to get mounted drive's volume name in linu

2020-04-14 09:14发布

问题:

I'm currently working on program, which must display information about mounted flash drive. I want to display full space, free space, file system type and volume name. But problem is that, i can't find any API through which i can get volume name(volume label). Is there any api to do this?

p.s. full space, free space and file system type i'm getting via statfs function

回答1:

Assuming that you work on a recent desktop-like distribution (Fedora, Ubuntu, etc.), you have HAL daemon running and a D-Bus session.

Within org.freedesktop.UDisks namespace you can find the object that represents this drive (say org/freedekstop/UDisks/devices/sdb/. It implements org.freedesktop.UDisks.interface. This interface has all the properties that you can dream of, including UUID (IdUuid), FAT label (IdLabel), all the details about filesystem, SMART status (if the drive supports that) etc. etc.

How to use D-Bus API in C is a topic for another question. I assume that's been already discussed in detail -- just search [dbus] and [c] tags.



回答2:

Flash drives are generally FAT32, which means the "name" that you're looking for is probably the FAT drive label. The most common linux command to retrieve that information is mlabel from the mtools package.

The command looks like this:

[root@localhost]$ mlabel -i /dev/sde1 -s ::
  Volume label is USB-DISK

This program works by reading the raw FAT header of the filesystem and retrieving the label from that data. You can look at the source code for the applciation to see how you can replicate the parsing of FAT data in your own application... or you can simply execute run the mlabel binary and read the result into your program. The latter sounds simpler to me.



回答3:

To call the methods:

 kernResult = self->FindEjectableCDMedia(&mediaIterator);
 if (KERN_SUCCESS != kernResult) {
     printf("FindEjectableCDMedia returned 0x%08x\n", kernResult);
 }

 kernResult = self->GetPath(mediaIterator, bsdPath, sizeof(bsdPath));
 if (KERN_SUCCESS != kernResult) {
     printf("GetPath returned 0x%08x\n", kernResult);
 }

and the methods:

// 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           kernResult;
    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 kernResult;
}

// 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 = '\0';
    *Path = '\0';

    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: %s\n", bsdPath);
                kernResult = KERN_SUCCESS;    
            }

            session = DASessionCreate(kCFAllocatorDefault);
            if(session == NULL) {
                qDebug("Can't connect to DiskArb\n");
                return -1;
            }

            disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, bsdPath);
            if(disk == NULL) {
                CFRelease(session);
                qDebug( "Can't create DADisk for %s\n",  bsdPath);
                return -1;
            }

            props = DADiskCopyDescription(disk);
            if(props == NULL) {
                CFRelease(session);
                CFRelease(disk);
                qDebug("Can't get properties for %s\n",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 kernResult;
}


标签: c linux