Discovering Well-Known directory locations

The Qt documentation, and in particular QDir, provide some helper methods to determine the location of certain directories in a portable manner. The current user's home directory, the root directory and finally the current temporary directory are all available via static factory methods on QDir. Additionally, the Qt docs mention in their Mac notes how to access the bundle path.

OS-X

On OS-X the most useful routine is FSFindFolder, a Carbon function which has existed in various forms since MacOS 7. It accepts a long list of constant codes, and a disk / domain specifier, which is used to specify the scope of the query. The standard domains are:

For some locations the domain is meaningless, but for most the domain maps onto the 'Library' structure. The network domain is relevant only when Network/Library has been defined by the directory service provider (NetInfo or LDAP, usually).

Note, the equivalent Cocoa functionaliy is provided by NSSearchPathForDirectoriesInDomains, but interfacing with the Carbon function is simpler, especially from C++ code.

QDir result;
FSRef fs;
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fs);
if (err != noErr) {
    qWarning() << "error doing FSFindFolder:" << err;
    return QDir();
}

CFURLRef dirURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &fs);
char fsRepr[1024];
if (!CFURLGetFileSystemRepresentation(dirURL, true, (UInt8*) fsRepr, 1024)) {
    qWarning() << "error invoking CFURLGetFileSystemRepresentation";
    return QDir();
}

result.setPath(QString::fromUtf8(fsRepr));
CFRelease(dirURL);
	

Some interesting locations:

Note that some of these paths can be discovered by other means, but using these APIs ensures portability across different locales and system configurations.

Windows

SHGetFolderPath and SHGetFolderLocation are the critical calls, available from Windows 2000 / ME and upwards. The required functionality can sometimes be provided on earlier versions of Windows via the re-distributable shfolder.dll. Like FSFindFolder on Mac, the calls accept a large list of symbolic constants and maps them to either a concrete path or to a 'virtual folder ID' (in the case of SHGetFolderLocation). Only a subset of locations can be mapped to a concrete path (see the MSDN docs), but in general the 'useful' ones can be - something like the Neighbourhood Network is a good example of a virtual location that can't be mapped to a path.

QDir result;
WCHAR fsRepr[MAX_PATH];
int flags; // 
if (S_OK != SHGetFolderPathW(NULL, csidl, flags, SHGFP_TYPE_CURRENT, fsRepr));
{
    qWarning() << "error doing SHGetFolderPath:";
    return QDir();	
}

result.setPath(QString::fromWCharArray(fsRepr));

Some interesting examples:

The current exhaustive list of constants can be found on MSDN (note this URL may break, but a search on 'CSIDL' should always work) In general the CSIDL consants containing 'COMMON' are losely equivalent to using the system domain on Mac; i.e for working with files that should be persistently available to every user on the machine.

Linux & Unix

There is not (at present) a standard runtime configuration for directory locations; the closest equivalent are the well-known locations defined as standards and conventions. FreeDesktop.org defines various standards, notably the Linux Standards Base and the Base Directory Specification, but adherance to these is variable. Practical compliance with such schemes generally means best-effor: trying them first, and falling back gracefully (and silently) to hard-coded locations (such as /usr/local/share).

Locations of visitors to this page