diff --git a/include/fat.h b/include/fat.h index b8c8113..b0ffc13 100644 --- a/include/fat.h +++ b/include/fat.h @@ -92,6 +92,11 @@ If there are open files, it will attempt to synchronise them to disc. */ extern void fatUnmount (const char* name); +/* +Get Volume Label +*/ +extern void fatGetVolumeLabel (const char* name, char *label); + #ifdef __cplusplus } #endif diff --git a/libogc/include/fat.h b/libogc/include/fat.h index 10f2af6..31efbe0 100644 --- a/libogc/include/fat.h +++ b/libogc/include/fat.h @@ -67,12 +67,18 @@ cacheSize specifies the number of pages to allocate for the cache. This will not startup the disc, so you need to call interface->startup(); first. */ extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage); + /* Unmount the partition specified by name. If there are open files, it will attempt to synchronise them to disc. */ extern void fatUnmount (const char* name); +/* +Get Volume Label +*/ +extern void fatGetVolumeLabel (const char* name, char *label); + #ifdef __cplusplus } #endif diff --git a/source/directory.c b/source/directory.c index 279a361..4edd7d9 100644 --- a/source/directory.c +++ b/source/directory.c @@ -329,7 +329,8 @@ bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry) { } lfn[lfnPos] = '\0'; // Set end of lfn to null character lfnChkSum = entryData[LFN_offset_checkSum]; - } if (lfnChkSum != entryData[LFN_offset_checkSum]) { + } + if (lfnChkSum != entryData[LFN_offset_checkSum]) { lfnExists = false; } if (lfnExists) { @@ -417,6 +418,49 @@ bool _FAT_directory_getRootEntry (PARTITION* partition, DIR_ENTRY* entry) { return true; } +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label) { + DIR_ENTRY entry; + DIR_ENTRY_POSITION entryEnd; + uint8_t entryData[DIR_ENTRY_DATA_SIZE]; + int i; + bool end; + + _FAT_directory_getRootEntry(partition, &entry); + + entryEnd = entry.dataEnd; + + // Make sure we are using the correct root directory, in case of FAT32 + if (entryEnd.cluster == FAT16_ROOT_DIR_CLUSTER) { + entryEnd.cluster = partition->rootDirCluster; + } + + label[0]='\0'; + label[11]='\0'; + end = false; + //this entry should be among the first 3 entries in the root directory table, if not, then system can have trouble displaying the right volume label + while(!end) { + if (_FAT_directory_incrementDirEntryPosition (partition, &entryEnd, false) == false) { + end = true; + } + + if(!_FAT_cache_readPartialSector (partition->cache, entryData, + _FAT_fat_clusterToSector(partition, entryEnd.cluster) + entryEnd.sector, + entryEnd.offset * DIR_ENTRY_DATA_SIZE, DIR_ENTRY_DATA_SIZE)) + { //error reading + return false; + } + if ((entryData[DIR_ENTRY_attributes] == ATTRIB_VOL)) { + for (i = 0; i < 11; i++) { + label[i] = entryData[DIR_ENTRY_name + i]; + } + return true; + } else if (entryData[0] == DIR_ENTRY_LAST) { + end = true; + } + } + return false; +} + bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry) { DIR_ENTRY_POSITION entryStart = entry->dataStart; DIR_ENTRY_POSITION entryEnd = entry->dataEnd; diff --git a/source/directory.h b/source/directory.h index 7ad5306..9342921 100644 --- a/source/directory.h +++ b/source/directory.h @@ -170,4 +170,9 @@ Fill in a stat struct based on a file entry */ void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); +/* +Get volume label +*/ +bool _FAT_directory_getVolumeLabel (PARTITION* partition, char *label); + #endif // _DIRECTORY_H diff --git a/source/libfat.c b/source/libfat.c index 6423298..0aacc38 100644 --- a/source/libfat.c +++ b/source/libfat.c @@ -69,12 +69,14 @@ bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSec devoptab_t* devops; char* nameCopy; + if(!name || !interface) + return false; + if(!interface->startup()) return false; - if(!interface->isInserted()) { + if(!interface->isInserted()) return false; - } devops = _FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); if (!devops) { @@ -109,6 +111,9 @@ void fatUnmount (const char* name) { devoptab_t *devops; PARTITION* partition; + if(!name) + return; + devops = (devoptab_t*)GetDeviceOpTab (name); if (!devops) { return; @@ -188,4 +193,49 @@ bool fatInitDefault (void) { return fatInit (DEFAULT_CACHE_PAGES, true); } +void fatGetVolumeLabel (const char* name, char *label) { + devoptab_t *devops; + PARTITION* partition; + char *buf; + int namelen,i; + if(!name || !label) + return; + + namelen = strlen(name); + buf=(char*)malloc(sizeof(char)*namelen+2); + strcpy(buf,name); + + if (name[namelen-1] == '/') { + buf[namelen-1]='\0'; + namelen--; + } + + if (name[namelen-1] != ':') { + buf[namelen]=':'; + buf[namelen+1]='\0'; + } + + devops = (devoptab_t*)GetDeviceOpTab(buf); + + for(i=0;buf[i]!='\0' && buf[i]!=':';i++); + if (!devops || strncasecmp(buf,devops->name,i)) { + free(buf); + return; + } + + free(buf); + + // Perform a quick check to make sure we're dealing with a libfat controlled device + if (devops->open_r != dotab_fat.open_r) { + return; + } + + partition = (PARTITION*)devops->deviceData; + + if(!_FAT_directory_getVolumeLabel(partition, label)) { + strncpy(label,partition->label,11); + label[11]='\0'; + } + if(!strncmp(label, "NO NAME", 7)) label[0]='\0'; +} diff --git a/source/partition.c b/source/partition.c index 7326024..cdd6794 100644 --- a/source/partition.c +++ b/source/partition.c @@ -206,6 +206,12 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach // Init the partition lock _FAT_lock_init(&partition->lock); + if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT16_volumeLabel), 11); + else + strncpy(partition->label, (char*)(sectorBuffer + BPB_FAT32_volumeLabel), 11); + partition->label[11] = '\0'; + // Set partition's disc interface partition->disc = disc; diff --git a/source/partition.h b/source/partition.h index c0e5c3e..52e6648 100644 --- a/source/partition.h +++ b/source/partition.h @@ -67,6 +67,7 @@ typedef struct { struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files mutex_t lock; // A lock for partition operations bool readOnly; // If this is set, then do not try writing to the disc + char label[12]; // Volume label } PARTITION; /*