#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/param.h>
#include "enums.h"
#include "structs.h"
#include "bless.h"
#include <CoreFoundation/CoreFoundation.h>
extern int blesscontextprintf(BLContextPtr context, int loglevel, char const *fmt, ...);
#define MISSINGMSG "<missing>"
static const char *messages[7][2] = {
{ "No Blessed System Folder", "Blessed System Folder is " },
{ "No Startup App folder (ignored anyway)", "Startup App folder is " },
{ "Open-folder linked list empty", "1st dir in open-folder list is " },
{ "No OS 9 + X blessed 9 folder", "OS 9 blessed folder is " },
{ "Unused field unset", "Thought-to-be-unused field points to " },
{ "No OS 9 + X blessed X folder", "OS X blessed folder is " },
{ "64-bit VSDB volume id not present", "64-bit VSDB volume id: " }
};
int modeInfo(BLContextPtr context, struct clarg actargs[klast]) {
int err;
CFDictionaryRef dict;
if(!actargs[kinfo].hasArg || actargs[kgetboot].present) {
char currentString[1024];
char currentDev[MNAMELEN];
struct statfs *mnts;
int vols;
if(BLIsOpenFirmwarePresent(context)) {
FILE *pop;
pop = popen("/usr/sbin/nvram boot-device", "r");
if(pop == NULL) {
blesscontextprintf(context, kBLLogLevelError, "Could not determine current boot device\n" );
return 1;
}
if(1 != fscanf(pop, "%*s\t%s\n", &(currentString[0]))) {
blesscontextprintf(context, kBLLogLevelError, "Could not parse output from /usr/sbin/nvram\n" );
return 1;
}
pclose(pop);
blesscontextprintf(context, kBLLogLevelVerbose, "Current OF: %s\n", currentString );
err = BLGetDeviceForOpenFirmwarePath(context, currentString,
currentDev);
if(err) {
blesscontextprintf(context, kBLLogLevelError, "Can't get device for %s: %d\n", currentString, err );
return 1;
}
} else {
struct statfs sb;
unsigned char parent[MNAMELEN];
unsigned long pnum = 0;
BLPartitionType ptype = 0;
if(0 != statfs("/", &sb)) {
blesscontextprintf(context, kBLLogLevelError, "Can't statfs /\n");
return 1;
}
err = BLGetParentDeviceAndPartitionType(context,
sb.f_mntfromname, parent, &pnum, &ptype);
if(err) {
blesscontextprintf(context, kBLLogLevelError, "Can't determine parent partition for %s\n", sb.f_mntfromname);
return 2;
}
if(ptype != kBLPartitionType_MBR) {
blesscontextprintf(context, kBLLogLevelError, "Incorrect partition map type\n");
return 3;
}
blesscontextprintf(context, kBLLogLevelVerbose, "Whole device is %s\n", parent);
err = BLGetActiveBIOSPartitionForDevice(context, parent, currentDev);
if(err) {
blesscontextprintf(context, kBLLogLevelError, "Can't determine active partition for %s\n", parent);
return 2;
}
blesscontextprintf(context, kBLLogLevelVerbose, "Active partition is %s\n", currentDev);
}
if( actargs[kgetboot].present) {
if(actargs[kplist].present) {
CFStringRef vol = CFStringCreateWithCString(kCFAllocatorDefault,
currentDev,
kCFStringEncodingUTF8);
CFMutableDictionaryRef dict = NULL;
CFDataRef tempData = NULL;
dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(dict, CFSTR("Boot Volume"), vol);
CFRelease(vol);
tempData = CFPropertyListCreateXMLData(kCFAllocatorDefault, dict);
write(fileno(stdout), CFDataGetBytePtr(tempData), CFDataGetLength(tempData));
CFRelease(tempData);
CFRelease(dict);
} else {
blesscontextprintf(context, kBLLogLevelNormal, "%s\n", currentDev);
}
return 0;
}
vols = getmntinfo(&mnts, MNT_NOWAIT);
if(vols == -1) {
blesscontextprintf(context, kBLLogLevelError, "Error gettings mounts\n" );
return 1;
}
while(--vols >= 0) {
if(strncmp(mnts[vols].f_mntfromname, currentDev, strlen(currentDev)+1) == 0) {
blesscontextprintf(context, kBLLogLevelVerbose, "mount: %s\n", mnts[vols].f_mntonname );
strcpy(actargs[kinfo].argument, mnts[vols].f_mntonname);
actargs[kinfo].hasArg = 1;
break;
}
}
if(!actargs[kinfo].hasArg) {
blesscontextprintf(context, kBLLogLevelError,
"Volume for OpenFirmware path %s is not available\n",
currentString);
return 2;
}
}
err = BLGetCommonMountPoint(context, actargs[kinfo].argument, "", actargs[kmount].argument);
if(err) {
blesscontextprintf(context, kBLLogLevelError, "Can't get mount point for %s\n", actargs[kinfo].argument );
return 1;
}
err = BLCreateVolumeInformationDictionary(context, actargs[kmount].argument,
&dict);
if(err) {
blesscontextprintf(context, kBLLogLevelError, "Can't print Finder information\n" );
return 1;
}
if(actargs[kplist].present) {
CFDataRef tempData = NULL;
tempData = CFPropertyListCreateXMLData(kCFAllocatorDefault, dict);
write(fileno(stdout), CFDataGetBytePtr(tempData), CFDataGetLength(tempData));
CFRelease(tempData);
} else {
CFArrayRef finfo = CFDictionaryGetValue(dict, CFSTR("Finder Info"));
int j;
CFNumberRef vsdbref;
uint64_t vsdb;
for(j = 0; j < (8-2); j++) {
CFDictionaryRef word = CFArrayGetValueAtIndex(finfo, j);
CFNumberRef dirID = CFDictionaryGetValue(word, CFSTR("Directory ID"));
CFStringRef path = CFDictionaryGetValue(word, CFSTR("Path"));
uint32_t dirint;
unsigned char cpath[MAXPATHLEN];
if(!CFNumberGetValue(dirID, kCFNumberLongType, &dirint)) {
continue;
}
if(dirint > 0 && CFStringGetLength(path) == 0) {
strcpy(cpath, MISSINGMSG);
} else {
if(!CFStringGetCString(path, cpath, MAXPATHLEN, kCFStringEncodingUTF8)) {
continue;
}
}
blesscontextprintf(context, kBLLogLevelNormal,
"finderinfo[%i]: %6lu => %s%s\n", j, dirint,
messages[j][dirint > 0], cpath);
}
vsdbref = CFDictionaryGetValue(dict, CFSTR("VSDB ID"));
CFNumberGetValue(vsdbref, kCFNumberSInt64Type, &vsdb);
blesscontextprintf(context, kBLLogLevelNormal, "%s 0x%016qX\n", messages[6][1],
vsdb);
}
CFRelease(dict);
return 0;
}