#include "msdos.h"␊ |
#include "ext2fs.h"␊ |
␊ |
#include "xml.h"␊ |
#include "disk.h"␊ |
␊ |
#include <limits.h>␊ |
#include <IOKit/storage/IOApplePartitionScheme.h>␊ |
#include <IOKit/storage/IOGUIDPartitionScheme.h>␊ |
|
struct DiskBVMap * map = NULL;␊ |
int bvCount = 0;␊ |
␊ |
const char *val;␊ |
char devsw[12];␊ |
const char *raw = 0;␊ |
char* val = 0;␊ |
int len;␊ |
␊ |
getValueForKey(kHidePartition, &raw, &len, &bootInfo->bootConfig);␊ |
if(raw) {␊ |
val = XMLDecode(raw); ␊ |
}␊ |
␊ |
/*␊ |
* Traverse gDISKBVmap to get references for␊ |
|
)␊ |
newBVR->visible = true;␊ |
␊ |
/*␊ |
* Looking for "Hide Partition" entries in "hd(x,y) hd(n,m)" format␊ |
/* Looking for "Hide Partition" entries in 'hd(x,y)|uuid|"label" hd(m,n)|uuid|"label"' format␊ |
* to be able to hide foreign partitions from the boot menu.␊ |
*/␊ |
␉␉␉if ( (newBVR->flags & kBVFlagForeignBoot)␊ |
␉␉␉␉␉&& getValueForKey(kHidePartition, &val, &len, &bootInfo->bootConfig)␊ |
␉␉␉␉ )␊ |
␉{␊ |
␉ sprintf(devsw, "hd(%d,%d)", BIOS_DEV_UNIT(newBVR), newBVR->part_no);␊ |
␉ if (strstr(val, devsw) != NULL)␊ |
newBVR->visible = false;␊ |
␉}␊ |
if ( (newBVR->flags & kBVFlagForeignBoot) )␊ |
{␊ |
if(val && matchVolumeToString(newBVR, val, true))␊ |
␉ newBVR->visible = false;␊ |
}␊ |
␊ |
/*␊ |
* Use the first bvr entry as the starting chain pointer.␊ |
|
#endif␊ |
␊ |
*count = bvCount;␊ |
␊ |
free(val); ␊ |
return chain;␊ |
}␊ |
␊ |
|
␊ |
//==========================================================================␊ |
␊ |
char* matchVolumeToString( BVRef bvr, const char* match, bool matchParcial)␊ |
{␊ |
␉char testStr[64];␊ |
␉ ␊ |
␉if ( !bvr || !match || !*match)␊ |
␉␉return false;␊ |
␉␊ |
␉if ( bvr->biosdev >= 0x80 && bvr->biosdev < 0x100␊ |
␉␉&& ( bvr->flags & ( kBVFlagSystemVolume|kBVFlagForeignBoot ) ) )␊ |
␉{␊ |
␉␉// Trying to match hd(x,y) format.␊ |
␉␉int len;␊ |
char *ret = 0;␊ |
␊ |
len = sprintf(testStr, "hd(%d,%d)", BIOS_DEV_UNIT(bvr), bvr->part_no);␊ |
␉␉if (matchParcial)␊ |
ret = strstr(match, testStr);␊ |
else if (!strcmp(match, testStr))␊ |
␉␉␉ret = (char*)match;␊ |
if(ret)␊ |
return ret+len;␊ |
␉␉␊ |
␉␉// Trying to match volume UUID.␊ |
␉␉if (bvr->fs_getuuid && bvr->fs_getuuid(bvr, testStr) == 0)␊ |
{␊ |
if (matchParcial)␊ |
ret = strstr(match, testStr);␊ |
else if (!strcmp(match, testStr))␊ |
ret = (char*)match;␊ |
if (ret)␊ |
return ret+strlen(testStr);␊ |
␉␉}␊ |
␊ |
␉␉// Trying to match volume label (always quoted).␊ |
␉␉if (bvr->description)␊ |
{ ␊ |
char *ret = 0, *temp = 0;␊ |
␊ |
bvr->description(bvr, testStr, sizeof(testStr)-1); ␊ |
␉␉␉if ( !(len = strlen(testStr)) )␊ |
return 0;␊ |
␊ |
len+=2; /* quoted */␊ |
temp = malloc(len+1);␊ |
if(!temp)␊ |
return 0;␊ |
␊ |
sprintf(temp, "\"%s\"", testStr);␊ |
␊ |
if(matchParcial)␊ |
ret = strstr(match, temp);␊ |
else if(!strcmp(match, temp))␊ |
ret = (char*)match;␊ |
␊ |
free(temp);␊ |
␊ |
if(ret)␊ |
return ret+len;␊ |
}␊ |
␉}␊ |
␉␊ |
␉return 0;␊ |
}␊ |
␊ |
/* If Rename Partition has defined an alias, then extract it for description purpose */␊ |
static const char * getVolumeLabelAlias( BVRef bvr, const char * str, long strMaxLen)␊ |
bool getVolumeLabelAlias( BVRef bvr, char* str, long strMaxLen)␊ |
{␊ |
const int MAX_ALIAS_SIZE=31;␊ |
static char szAlias[MAX_ALIAS_SIZE+1];␊ |
char *q=szAlias;␊ |
const char * szAliases = getStringForKey(kRenamePartition, &bootInfo->bootConfig);␊ |
/* The format for the rename string is the following:␊ |
hd(x,y)|uuid|"label" "alias";hd(m,n)|uuid|"label" etc; ...␊ |
*/␊ |
char *aliasList;␊ |
char *next;␊ |
if( !str || strMaxLen <= 0)␊ |
return false;␊ |
␊ |
if( !(aliasList = XMLDecode(getStringForKey(kRenamePartition, &bootInfo->bootConfig))) )␊ |
return false;␊ |
␊ |
for(next = aliasList;␊ |
next && *next;␊ |
)␊ |
{␊ |
char *start, *aliasStart, *aliasEnd;␊ |
char *ret;␊ |
␊ |
start = aliasStart = (char*)matchVolumeToString(bvr, next, true);␊ |
if(!start || !*start)␊ |
break;␊ |
␊ |
/* Find and delimit the current entry's end */␊ |
next = strstr(start, ";");␊ |
if(next)␊ |
{␊ |
/* Not enough characters for a successful match: we'd need at least␊ |
* one space and another char. before the semicolon␊ |
*/␊ |
if(next-start < 2) {␊ |
next++;␊ |
continue;␊ |
}␊ |
␊ |
*next = '\0';␊ |
next++;␊ |
}␊ |
␊ |
/* Check for at least one space, but ignore the rest of them */␊ |
while(isspace(*aliasStart))␊ |
aliasStart++;␊ |
if(start == aliasStart)␊ |
continue;␊ |
␊ |
if (!str || !*str || !szAliases) return 0; // no renaming wanted␊ |
␊ |
const char * p = strstr(szAliases, str);␊ |
if(!p || !(*p)) return 0; // this volume must not be renamed, or option is malformed␊ |
␊ |
p+= strlen(str); // skip the "hd(n,m) " field␊ |
// multiple aliases can be found separated by a semi-column␊ |
while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++;␊ |
*q='\0';␊ |
␊ |
return szAlias;␊ |
␉␉switch(*aliasStart)␊ |
{␊ |
case '\0':␊ |
␉␉␉␉break;␊ |
␉␉␉/* If the string is quoted, skip the starting quote, find the ending␊ |
* one, and zero it to end the string.␊ |
* If we succeed, fall-through to the final copy-and-cleanup part */␊ |
case '"':␊ |
aliasStart++;␊ |
␉␉␉␉aliasEnd = strstr(aliasStart, "\"");␊ |
␉␉␉␉if(!aliasEnd || aliasStart == aliasEnd)␊ |
␉␉␉␉␉break;␊ |
␊ |
␉␉␉␉*aliasEnd = '\0';␊ |
default:␊ |
ret = strncpy(str, aliasStart, strMaxLen); ␊ |
free(aliasList);␊ |
␊ |
return ret != 0;␊ |
}␊ |
}␊ |
␊ |
free(aliasList);␊ |
return false;␊ |
}␊ |
␊ |
void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen, bool verbose )␊ |
void getBootVolumeDescription( BVRef bvr, char *str, long strMaxLen, bool verbose )␊ |
{␊ |
unsigned char type = (unsigned char) bvr->part_type;␊ |
char *p;␊ |
unsigned char type;␊ |
char*p = str;␊ |
␊ |
if(!bvr || !p || strMaxLen <= 0)␊ |
return;␊ |
␊ |
type = (unsigned char) bvr->part_type;␊ |
␉␊ |
if (verbose)␊ |
{␊ |
int len = getDeviceDescription(bvr, str);␊ |
strcat(str, " ");␊ |
for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--);␊ |
}␊ |
␉␊ |
p = str;␊ |
if (verbose) {␊ |
getDeviceDescription(bvr, str);␊ |
strcat(str, " ");␊ |
for (; strMaxLen > 0 && *p != '\0'; p++, strMaxLen--);␊ |
/* See if a partition rename is preferred */␊ |
if(getVolumeLabelAlias(bvr, p, strMaxLen)) {␊ |
printf("Renamed: %s\n", p);␊ |
strncpy(bvr->label, p, sizeof(bvr->label)-1); ␊ |
return; // we're done here no need to seek for real name␊ |
}␊ |
␊ |
// See if we should get the renamed alias name for this partion:␊ |
const char * szAliasName = getVolumeLabelAlias(bvr, str, strMaxLen);␊ |
if (szAliasName && *szAliasName)␊ |
{␊ |
␉strncpy(bvr->label, szAliasName, strMaxLen);␊ |
␉return; // we're done here no need to seek for real name␊ |
}␊ |
␊ |
//␊ |
// Get the volume label using filesystem specific functions␊ |
// or use the alternate volume label if available.␊ |
//␊ |
␉ if (*bvr->altlabel == '\0')␊ |
␉ {␊ |
if (bvr->description)␊ |
␉if (*bvr->altlabel != '\0')␊ |
strncpy(p, bvr->altlabel, strMaxLen);␊ |
␉else if (bvr->description)␊ |
bvr->description(bvr, p, strMaxLen);␊ |
}␊ |
else␊ |
␉ strncpy(p, bvr->altlabel, strMaxLen);␊ |
␊ |
if (*p == '\0') {␊ |
const char * name = getNameForValue( fdiskTypes, type );␊ |
if (name == NULL) {␊ |
name = bvr->type_name;␊ |
}␊ |
if (name == NULL) {␊ |
sprintf(p, "TYPE %02x", type);␊ |
} else {␊ |
strncpy(p, name, strMaxLen);␊ |
}␊ |
const char * name = getNameForValue( fdiskTypes, type );␊ |
if (name == NULL) {␊ |
name = bvr->type_name;␊ |
}␊ |
if (name == NULL) {␊ |
sprintf(p, "TYPE %02x", type);␊ |
} else {␊ |
strncpy(p, name, strMaxLen);␊ |
}␊ |
}␊ |
␊ |
/* See if a partion rename is wanted: */␊ |
␊ |
␊ |
// Set the devices label␊ |
sprintf(bvr->label, p);␊ |
strncpy(bvr->label, p, sizeof(bvr->label)-1);␊ |
}␊ |
␊ |
//==========================================================================␊ |