VFS Manager
The VFS (Virtual File System) Manager provides a unified API that gives applications access to many different file systems on many different media types. It abstracts the underlying file systems so that applications can be written without regard to the actual file system in use. The VFS Manager includes APIs for manipulating files, directories, and volumes.
NOTE: Although the great majority of the functions in the VFS Manager can be used by any application, some are intended only for use by drivers and file systems. Others are not intended for use by third-party applications but are designed primarily for system use.
The VFS Manager, the Data Manager, and File Streaming APIs
With the addition of the VFS Manager to Palm OS®, there are now three distinct ways applications can store and retrieve Palm OS user data:
- The Data Manager manages user data in the storage heap. Use them to store and retrieve Palm OS user data when storage on the handheld is all that is needed, or when efficient access to data is paramount.
- The File Streaming API is a layer on top of the Data Manager that provides file functionality with all data being read from or written to a database in the storage heap. Most applications have no need for the File Streaming APIs; they are primarily used by applications that need to work with large blocks of data.
- The VFS and Expansion Managers were designed specifically to support many types of expansion memory as secondary storage. The VFS Manager APIs present a consistent interface to many different types of file systems on many types of external media. Applications that use the VFS APIs can support the widest variety of file systems. Use the VFS Manager when your application needs to read and write data stored on external media.
Palm OS applications should use the appropriate APIs for each given situation. The Data Manager, being an efficient manager of storage in the storage heap, should be used whenever access to external media is not absolutely needed. Use the VFS API when interoperability and file system access is needed.
For more information on the Data and Resource Managers, as well as on the File Streaming APIs, see Chapter 2, "Palm OS Databases." For details of the APIs presented by the VFS Manager, see Chapter 8, "VFS Manager."
Checking for the Presence of the VFS Manager
Because not every system has (or needs) Virtual File System (VFS) Manager services, applications wishing to use these services should check to make sure they are present before calling them. This is accomplished by checking for the VFS Manager's system feature with a call to FtrGet()
, supplying sysFileCVFSMgr
for the feature creator and vfsFtrIDVersion
for the feature number.
The following code shows how to check for the presence and proper version of the VFS Manager. Note that expectedVFSMgrVersionNum
should be replaced by the actual version number you expect.
uint32_t vfsMgrVersion; Err err; err = FtrGet(sysFileCVFSMgr, vfsFtrIDVersion, &vfsMgrVersion); if(err){ // VFS Manager not installed } else { // check version number of VFS Manager, if necessary if(vfsMgrVersion == expectedVFSMgrVersionNum) // everything is OK }
Standard Directories
The user experience presented by Palm OS is simpler and more intuitive than that of a typical desktop computer. Part of this simplicity arises from the fact that Palm OS doesn't present a file system to the user. Users don't have to understand the complexities of a typical file system; applications are readily available with one or two taps of a button or icon, and data associated with those applications is accessible only through each application. Maintaining this simplicity of user operation while supporting a file system on an expansion card is made possible through a standard set of directories on the expansion card.
The following table lists the standard directory layout for all "standards compliant" Palm OS secondary storage. All Palm OS relevant data should be in the /PALM
directory (or in a subdirectory of the /PALM
directory), effectively partitioning off a private name space.
The Palm OS Launcher is expansion card aware. When an expansion card containing a file system is inserted, all applications listed in the card's /PALM/Launcher
directory are automatically added to a new Launcher category. This new category takes the name of the expansion card volume. Note that the name displayed in the Launcher for a given application is the name in the application's tAIN
(application icon name) resource or, if this resource is empty, the database name, which may or may not match the name of the file.
NOTE: Whenever possible give the same name to the
.prc
file and to the database. If the .prc
filename differs from the database name, and users copy your application from the card to the handheld and then to another card, the filename may change. This is because the database name is used when an application is copied from the handheld to the card.
When a writable volume is mounted, the Launcher automatically creates the /PALM
and /PALM/Launcher
directories if they don't already exist. If they do, and if there are applications present in the /PALM/Launcher
directory, the Launcher automatically switches to the card's list of applications unless it runs start.prc
.
In addition to these standard directories, the VFS Manager supports the concept of a default directory; a directory in which data of a particular type is typically stored. See "Determining the Default Directory for a Particular File Type" for more information.
Applications on Cards
Palm OS applications located in the /PALM/Launcher
directory of an expansion card volume appear in a separate Launcher category when the card is inserted into the handheld's expansion slot. If you tap the icon for one of these applications, it is copied to main memory and then launched.
Applications launched from a card ("card-launched" applications) are first sent a sysAppLaunchCmdCardLaunch
launch code, along with a parameter block that includes the reference number of the volume on which the application resides and the complete path to the application. When processing this launch code, the application shouldn't interact with the user or access globals. Unless the application sets the sysAppLaunchStartFlagNoUISwitch
bit in the start
flags (which are part of the parameter block), the application is then sent a sysAppLaunchCmdNormalLaunch
launch code. This is when the application should, if it needs to, interact with user. Applications may want to save some state when sysAppLaunchCmdCardLaunch
is received, then act upon that state information when sysAppLaunchCmdNormalLaunch
is received.
When the user switches to a new application, the card-launched application is removed from main memory. Note, however, that any databases created by the card-launched application remain.
There are certain implications to this "copy and run" process:
- There must be sufficient memory for the application. If the handheld doesn't have enough memory to receive the application, it isn't copied from the expansion card and it isn't launched.
- The copying process takes time. For large applications, this can cause a noticeable delay before the application is actually launched.
- If some version of the application on the card is already present in main memory, the Launcher puts up a dialog that requires the user to choose whether or not to overwrite the in-memory version.
- Card-launched applications have a limited lifetime: applications reside in main memory only while they are running. When the user switches to a different application, the card-launched application that was just running is removed from main memory. If the card-launched application is then re-launched, it is once again copied into the handheld's memory.
- "Legacy" applications—those that are unaware that they are being launched from a card—only work with databases in main memory. Associated databases aren't copied to main memory along with the application unless the database is bundled with the application. Databases created by card-launched applications are not removed along with the application, however, so this data is available to the application when it is subsequently run. Applications that are written to take advantage of the VFS Manager can read and write data on the expansion card, so this limitation generally only applies to legacy applications.
Bundled databases, although copied to main memory along with their associated application, are meant for static data that doesn't change, such as a game level database. Bundled databases are not copied back to the card; they are simply deleted from memory when the user chooses another application. To bundle a database with an application, give it the same creator ID as the owning application, set the
dmHdrAttrBundle
bit, and place it in the/PALM/Launcher
directory along with the application. - Unless a card-launched application is running, it doesn't receive notifications or launch codes since it isn't present on the handheld. In particular, these applications don't receive notifications and aren't informed when an alarm is triggered.
Volume Operations
If an expansion card supports a file system, the VFS Manager allows you to perform a number of standard volume operations. To determine which volumes are currently mounted and available, use VFSVolumeEnumerate()
. This function, the use of which is illustrated in "Checking for Mounted Volumes" of Exploring Palm OS: System Management returns a volume reference number that you then supply to the remainder of the volume operations.
When the user inserts a card containing a mountable volume into a slot (note that the current implementation only supports one volume per slot), the VFS Manager attempts to mount the volume automatically. You should rarely, if ever, have to mount volumes directly. You can attempt to mount a volume using a different file system, however, perhaps after installing a new file system driver on the handheld. To explicitly mount or unmount a volume, use VFSVolumeMount()
and VFSVolumeUnmount
. When mounting a volume, you can either specify an explicit file system with which to mount the volume, or you can request that the VFS Manager try to determine the appropriate file system. If the VFS Manager cannot mount the volume using any of the available file systems, it attempts to format the volume using a file system deemed appropriate for the slot, and then mount it. See the description of VFSVolumeMount()
in Chapter 8, "VFS Manager," for the precise arguments you must supply when explicitly mounting a volume.
Use VFSVolumeFormat()
to format a volume. This function can be used to change the file system on the expansion card; you can explicitly indicate a file system to use when formatting it. Once the card has been formatted, the VFS Manager automatically mounts it; a new volume reference number is returned from VFSVolumeFormat()
.
The VFSVolumeGetLabel()
and VFSVolumeSetLabel()
functions get and set the volume label, respectively. Since the file system is responsible for verifying the validity of strings, you can try to set the volume label to any desired value. If the file system doesn't natively support the name given, the VFS Manager creates the /VOLUME.NAM
file used to support long volume names (see "Naming Volumes" for more information) or you get an error back if the file system doesn't support the supplied string.
Additional information about the volume can be obtained through the use of VFSVolumeSize()
and VFSVolumeInfo()
. As the name implies, VFSVolumeSize()
returns size information about the volume. In particular, it returns both the total amount of space on the volume, in bytes, and the amount of that volume's space that is currently in use, again in bytes. VFSVolumeInfo()
returns various pieces of information about the volume, including:
- whether the volume is hidden
- whether the volume is read-only
- whether the volume is supported by a block device driver, or is being simulated by Palm OS Emulator
- the type and creator of the underlying file system
- the slot with which the volume is associated, and the reference number of the driver controlling the slot
- the type of media on which this volume is located, such as SD, CompactFlash, or Memory Stick
All of the above information is returned encapsulated within a VolumeInfoType
structure. Whether the volume is hidden or read-only is further encoded into a single field within this structure; see Volume Attributes in Chapter 8, "VFS Manager," for the bits that make up this field.
Hidden Volumes
Included among the volume attributes is a "hidden" bit, vfsVolumeAttrHidden
, that indicates whether the volume on the card is to be visible or hidden. Hidden volumes are typically not meant to be directly available to the user; the Launcher and the CardInfo application both ignore all hidden volumes.
To make a volume hidden, simply create an empty file named HIDDEN.VOL
in the /PALM
directory. The VFSVolumeInfo()
function looks for this file and, if found, returns the vfsVolumeAttrHidden
bit along with the volume's other attributes.
Matching Volumes to Slots
Many applications don't need to know the specifics of an expansion card as provided by the ExpCardInfo()
function. Often, the information provided by the VFSVolumeInfo()
function is enough. Some applications need to know more about a particular volume, however. The name of the manufacturer or the type of card, for instance, may be important.
The VolumeInfoType
structure returned from VFSVolumeInfo()
contains a slotRefNum
field that can be passed to ExpCardInfo()
. This allows you to obtain specific information about the card on which a particular volume is located.
Although block device drivers currently only support one volume per slot, obtaining volume information that corresponds to a given slot reference number isn't quite so simple, since there isn't a function that returns the volume reference number given a slot reference number. You can, however, iterate through the mounted volumes and check each volume's slot reference number. This is the technique that the CardInfo application uses.
Naming Volumes
Different file system libraries support volume names of different maximum lengths and have different restrictions on character sets. The file system library is responsible for verifying whether or not a given volume name is valid, and returns an error if it is not. From a Palm OS developer's standpoint, volume names can be up to 255 characters long, and can include any printable character.
The file system library is responsible for translating the volume name into a format that is acceptable to the underlying file system. For example, in a file system where the 8.3 naming convention is used for filenames, to translate a long volume name the first eleven valid, non-space characters are used. Valid characters in this instance are A-Z, 0-9, $, %, ', -, _, @, ~, ', !, (, ), ^, #, and &.
When the underlying file system doesn't support a long volume name, VFSVolumeSetLabel()
creates the file /VOLUME.NAM
in an effort to preserve the long volume name. This file contains the following, in order:
File Operations
Most of the familiar operations you'd use to operate on files in a desktop application are supported by the VFS Manager; these are listed in "Common Operations," below. In addition, the VFS Manager includes a set of functions that simplify the way you work with files that represent Palm OS databases (.pdb
) or Palm resource databases (.prc
). These are covered in "Working with Palm OS Databases."
Common Operations
The VFS Manager provides many standard file operations that should be familiar from desktop and larger computer systems. Because these functions work largely as you would expect, their use isn't detailed here. See the descriptions of each individual function in Chapter 8, "VFS Manager," for the arguments, return values, and side effects of each.
Note that some of these functions can be applied to both files and directories, while others work only with files.
Table 3.1 Common file operations
Open a file, given a volume reference number and a file path. |
|
Read data from a file into the dynamic heap or any writable memory. |
|
Read data from a file into a chunk of memory in the storage heap. |
|
Set the position within an open file from which to read or write. |
|
Get the current position of the file pointer within an open file. |
|
Create a file, given a volume reference number and a file path. |
|
Obtain the attributes of an open file, including hidden, read-only, system, and archive bits. See "File and Directory Attributes" in Chapter 8, "VFS Manager," for the bits that make up the attributes field. |
|
Set the attributes of an open file, including hidden, read-only, system, and archive bits. |
|
Get the created, modified, and last accessed dates for an open file. |
|
Set the created, modified, and last accessed dates for an open file. |
Once a file has been opened, it is identified by a unique reference number: a FileRef
. Functions that work with open files take a file reference. Others, such as VFSFileOpen()
, require a volume reference and a path that identifies the file within the volume. Note that all paths are volume relative, and absolute within that volume: the VFS Manager has no concept of a "current working directory," so relative path names are not supported. The directory separator character is the forward slash: "/". The root directory for the specified volume is specified by a path of "/".
Naming Files
Different file systems support filenames and paths of different maximum lengths. The file system library is responsible for verifying whether or not a given path is valid and returns an error if it is not valid. From an application developer's standpoint, filenames can be up to 255 characters long and can include any normal character including spaces and lower case characters in any character set. They can also include the following special characters:
$ % ' - _ @ ~
' ! ( ) ^ # & + , ; = [ ]
The file system library is responsible for translating each filename and path into a format that is acceptable to the underlying file system. For example, when the 8.3 naming convention is used to translate a long filename, the following guidelines are used:
- The name is created from the first six valid, non-space characters which appear before the last period. The only valid characters are A-Z, 0-9, $, %, ', -, _, @, ~, ', !, (, ), ^, #, and &.
- The extension is the first three valid characters after the last period.
- The end of the six byte name has "~1" appended to it for the first occurrence of the shortened filename. Each subsequent occurrence uses the next unique number, so the second occurrence would have "~2" appended, and so on.
The standard VFAT file system library provided with all Palm Powered™ handhelds that support expansion uses the above rules to create FAT-compliant names from long filenames.
Working with Palm OS Databases
Expansion cards are often used to hold Palm OS applications and data. Due to the way that secondary storage media are connected to the Palm Powered handheld, applications cannot be run directly from the expansion card, nor can databases be manipulated using the Data Manager without first transferring them to main memory. Applications written to use the VFS Manager, however, can operate directly on files located on an expansion card.
NOTE: Whenever possible give the same name to the
.prc
file and to the database. If the .prc
filename differs from the database name, and the user copies your application from the card to the handheld and then to another card, the filename may change. This is because the database name is used when an application is copied from the handheld to the card.
Stand-Alone Applications
To allow the user to run an application that is self-contained—that isn't accompanied by a separate database—you need only do one of two things:
- If the application is to be run whenever the card is inserted into the expansion slot, simply name the application
start.prc
and place it in the/PALM
directory. The operating system takes care of transferring the application to main memory and starting it automatically. - If the application is to be run on-demand, place it in the
/PALM/Launcher
directory. All applications located in this directory appear in the launcher when the user selects the category bearing the name of the expansion card.
Both of these mechanisms allow applications that were written without any knowledge of the VFS or Expansion Manager APIs to be run from a card. Because they are transferred to main memory prior to being run, such applications need not know that they are being run from an expansion card. Databases created by these applications are placed in the storage heap, as usual. When the card containing the application is removed, the application disappears from main memory unless it is running, in which case it remains until such time as the application is no longer running. Any databases it created remain. When the card is re-inserted and the application re-run, it is once again copied into main memory and is able to access those databases.
Applications with Static Data
Many applications are accompanied by one or more associated Palm OS databases when installed. These applications, at least to a limited degree, need to be cognizant of the fact that they reside on an expansion card.
If there is no specific requirement for the application's data to be stored in Palm OS database format, you may want to use the VFS Manager's many file I/O operations to read and write the data on the card. Because of the large data storage capabilities of the expansion media relative to the handheld's memory, this latter solution is the one preferred by applications where large capacity data storage is a key feature.
Bundled Databases
When an application is launched from a card using the launcher, any bundled databases present in the /PALM/Launcher
directory are also imported. Bundled databases have the same creator as the "owning" application and have the dmHdrAttrBundle
bit set. Note that bundled databases are intended only for read-only data, such as a game-level database. Bundled databases are removed from main memory along with the application when the user switches to another application and are not copied back to the expansion card.
Transferring Palm OS Databases to and from Expansion Cards
The VFSExportDatabaseToFile()
function converts a database from its internal format on the handheld to its equivalent file format and transfers it to an expansion card. The VFSImportDatabaseFromFile()
function does the reverse; it transfers the file from the expansion card to main memory and converts it to the internal format used by Palm OS. Use these functions when moving Palm OS databases between main memory and an expansion card.
VFSExportDatabaseToFile()
and VFSImportDatabaseFromFile()
, depending on the size of the database and the mechanism by which it is being transferred, can take some time. Use VFSExportDatabaseToFileCustom()
and VFSImportDatabaseFromFileCustom()
if you want to display a progress dialog or allow the user to cancel the operation. These functions make repeated calls to a callback function that you specify; within this callback function you can update a progress indicator. The return value from your callback determines whether the database transfer should proceed; return errNone
if it should continue, or return any other value to abort the process. See the documentation for VFSExportProcPtr()
and VFSImportProcPtr()
in Chapter 8, "VFS Manager," for the format of each callback function.
The following code excerpt illustrates the use of VFSImportDatabaseFromFileCustom()
with a progress tracker.
Listing 3.1 Using VFSImportDatabaseFromFileCustom()
typedef struct { ProgressType *progressP; const Char *nameP; } CBDataType, *CBDataPtr; static Boolean ProgressTextCB(PrgCallbackDataPtr cbP) { const Char *nameP = ((CBDataPtr) cbP->userDataP)->nameP; // Set up the progress text to be displayed StrPrintF(cbP->textP, "Importing %s.", nameP); cbP->textChanged = true; return true; // So what we specify here is used to update the dialog } static Err CopyProgressCB(UInt32 size, UInt32 offset, void *userDataP) { CBDataPtr CBDataP = (CBDataPtr) userDataP; if (offset == 0) { // If we're just starting, we need to set up the dialog CBDataP->progressP = PrgStartDialog("Importing Database", ProgressTextCB, CBDataP); if (!CBDataP->progressP) return memErrNotEnoughSpace; } else { EventType event; Boolean handled; do { EvtGetEvent(&event, 0); // Check for events handled = PrgHandleEvent(CBDataP->progressP, &event); if (!handled) { // Did the user tap the "Cancel" button? if( PrgUserCancel(CBDataP->progressP) ) return exgErrUserCancel; } } while(event.eType != sysEventNilEvent); } return errNone; } static Err ImportFile(UInt16 volRefNum, Char *pathP, Char *nameP, UInt16 *cardNoP, LocalID *dbIDP) { CBDataType userData; Char fullPathP[256]; Err err; userData.progressP = NULL; userData.nameP = nameP; StrPrintF(fullPathP, "%s/%s", pathP, nameP); // rebuild full path to the file err = VFSImportDatabaseFromFileCustom(volRefNum, fullPathP, cardNoP, dbIDP, CopyProgressCB, &userData); if (userData.progressP) // If the progress dialog was displayed, remove it. PrgStopDialog(userData.progressP, (err == exgErrUserCancel) ); return err; }
Exploring Palm OS Databases on Expansion Cards
The VFS Manager includes functions specifically designed for exploring the contents of a Palm OS database located on an expansion card. This access is read-only, however. You can extract individual records and resources from a database, and you can determine information such as the last modification date of a database on an expansion card. But there aren't parallel functions to write records and resources to a database or to update database-specific information for a database that is located on an expansion card. To do this you need to import the database into main memory, make the necessary changes, and then export it back to the expansion card.
To obtain a single record from a database located on an expansion card without first importing the database into main memory, use VFSFileDBGetRecord()
. This function is analogous to DmGetRecord()
but works with files on an external card rather than with databases in main memory. It transfers the specified record to the storage heap after allocating a handle of the appropriate size. Note that you'll need to free this memory, using MemHandleFree()
, when the record is no longer needed.
The VFSFileDBGetResource()
function operates in a similar fashion, but instead of loading a particular database record it loads a specified resource from a resource database located on an expansion card. This resource is put onto the storage heap. Again, free this memory once the resource is no longer needed.
To obtain more general information about a database on an external card, use VFSFileDBInfo()
. In addition to the information you could obtain about any file on an external card using the VFSFileGetAttributes()
and VFSFileGetDate()
functions, VFSFileDBInfo()
returns:
- the database name
- the version of the database
- the number of times the database was modified
- the application info block handle
- the sort info block handle
- the database's type
- the database's creator
- the number of records in the database
NOTE: The functions described in this section incur a lot of overhead in order to parse the database file format. Frequent use of these functions is not recommended. Also, if you request either the application info block handle or the sort info block handle, you must free the handle when it is no longer needed.
Directory Operations
Many of the familiar operations you'd use to operate on directories are supported by the VFS Manager; these are listed in "Common Operations", below. One common operation—determining the files that are contained within a given directory—is covered in some detail in "Enumerating the Files in a Directory." To improve data interchange with devices that aren't running Palm OS, expansion card manufacturers have specified default directories for certain file types. "Determining the Default Directory for a Particular File Type" discusses how you can both determine and set the default directory for a given file type.
Directory Paths
All paths are volume relative and absolute within that volume: the VFS Manager has no concept of a "current working directory," so relative path names are not supported. The directory separator character is the forward slash: "/". The root directory for the specified volume is specified by a path of "/".
Common Operations
The VFS Manager provides many of the standard directory operations that should be familiar from desktop and larger computer systems. Because these functions work largely as you would expect, their use isn't detailed here. See the descriptions of each individual function in Chapter 8, "VFS Manager," for the arguments, return values, and side effects of each.
Note that most of these functions can be applied to files as well as directories.
Table 3.2 Common directory operations
Obtain the attributes of an open directory, including hidden, read-only, system, and archive bits. See "File and Directory Attributes" in Chapter 8, "VFS Manager," for the bits that make up the attributes field. |
|
Set the attributes of an open directory, including hidden, read-only, system, and archive bits. |
|
Get the created, modified, and last accessed dates for an open file. |
|
Set the created, modified, and last accessed dates for an open file. |
Enumerating the Files in a Directory
Enumerating the files within a directory is made simple due to the presence of the VFSDirEntryEnumerate()
function. The use of this function is illustrated below. Note that volRefNum
and dirPathStr
must be declared and initialized prior to the following code.
Listing 3.2 Enumerating a directory's contents
// Open the directory and iterate through the files in it. // volRefNum must have already been defined. err = VFSFileOpen(volRefNum, "/", vfsModeRead, &dirRef); if(err == errNone) { // Iterate through all the files in the open directory UInt32 fileIterator; FileInfoType fileInfo; FileRef dirRef; Char *fileName = MemPtrNew(256); // should check for err fileInfo.nameP = fileName; // point to local buffer fileInfo.nameBufLen = 256; fileIterator = expIteratorStart; while (fileIterator != expIteratorStop) { // Get the next file err = VFSDirEntryEnumerate(dirRef, &fileIterator, &fileInfo); if(err == errNone) { // Process the file here. } } else { // handle directory open error here } MemPtrFree(fileName); }
Each time through the while loop, VFSDirEntryEnumerate()
sets the FileInfoType
structure as appropriate for the file currently being enumerated. Note that if you want the filename, it isn't enough to simply allocate space for the FileInfoType
structure; you must also allocate a buffer for the filename, set the appropriate pointer to it in the FileInfoType
structure, and specify your buffer's length. Since the only other information encapsulated within FileInfoType
is the file's attributes, most applications will want to also know the file's name.
Note that enumeration in the VFS Manager assumes that you are not changing the file set being enumerated. That is, you cannot delete or add files without restarting the enumeration.
Determining the Default Directory for a Particular File Type
As explained in "Standard Directories," the expansion capabilities of Palm OS include a mechanism to map MIME types or file extensions to specific directory names. This mechanism is specific to the block device driver: where an image might be stored in the "/Images" directory on a Memory Stick, on an MMC card it may be stored in the "/DCIM" directory. The VFS Manager includes a function that enables you to get the default directory on a particular volume for a given file extension or MIME type, along with functions that allow you to register and un-register your own default directories.
The VFSGetDefaultDirectory()
function takes a volume reference and a string containing the file extension or MIME type and returns a string containing the full path to the corresponding default directory. When specifying the file type, either supply a MIME media type/subtype pair, such as "image/jpeg", "text/plain", or "audio/basic"; or a file extension, such as ".jpeg
". As with most other Palm OS functions, you'll need to pre-allocate a buffer to contain the returned path. Supply a pointer to this buffer along with the buffer's length. The length is updated upon return to indicate the actual length of the path, which won't exceed the originally-specified buffer length.
The default directory registered for a given file type is intended to be the "root" default directory. If a given default directory has one or more subdirectories, applications should also search those subdirectories for files of the appropriate type.
VFSGetDefaultDirectory()
allows you to determine the directory associated with a particular file suffix. However, there's no way to get the entire list of file suffixes that are mapped to default directories. For this reason, CardInfo keeps its own list of possible file suffixes. It iterates through this list, calling VFSGetDefaultDirectory()
for each file suffix to get the full path to the corresponding default directory. It then looks into each default directory for files that match the expected suffix or suffixes for that directory.
Registering New Default Directories
In addition to the default directories that the underlying driver is already aware of, you can create your own mappings between files of a given type and a specific directory on a particular kind of external storage card. Most applications don't need this functionality; it is generally used by a block device driver to register those files and media types that are supported by that driver. However, VFSRegisterDefaultDirectory()
and its opposite, VFSUnregisterDefaultDirectory()
, are available to those applications that need them. Such applications should generally register the desired file types for expMediaType_Any
. This is a wildcard which works for all media types; it can be overridden by a registration that specifies a real media type.
NOTE: Registering a directory as the default location for files of a given type on a particular type of media doesn't automatically register that file type with HotSync Exchange. See "HotSync Exchange" of Exploring Palm OS: High-Level Communications for information on registering file types with HotSync Exchange.
If a default directory has already been registered for a given file/media type combination, applications should use the pre-existing registration instead of establishing a new one. Existing registrations should generally not be removed.
Default Directories Registered at Initialization
The VFS Manager registers the following under the expMediaType_Any
media type, which VFSGetDefaultDirectory()
reverts to when there is no default registered by the block device driver for a given media type.
Table 3.3 Default registrations
These registrations are intended to aid applications developers, but you aren't required to follow them. Although you can choose to ignore these registrations, by following them you'll improve interoperability between applications and other devices. For example, a digital camera which conforms to the media specifications will put its pictures into the registered directory (or a subdirectory of it) appropriate for the image format and media type. By looking up the registered directory for that format, an image viewer application on the handheld can easily find the images without having to search the entire card. These registrations also help prevent different developers from hard-coding different paths for specific file types. Thus, if a user has two different image viewer applications, both will look in the same location and find the same set of images.
Registering these file types at initialization allows you to use the HotSync®
process to transfer files of these types to an expansion card. During the HotSync process, files of the registered types are placed directly in the specified directories on the card.
Custom Calls
Recognizing that some file systems may implement functionality not covered by the APIs included in the VFS and Expansion Managers, the VFS Manager includes a single function that exists solely to give developers access to the underlying file system. This function, VFSCustomControl()
, takes a registered creator code and a selector that together identify the operation that is to be performed. VFSCustomControl()
can either request that a specific file system perform the specified operation, or it can iterate through all of the currently-registered file systems in an effort to locate one that responds to the desired operation.
Parameters are passed to the file system's custom function through a single VFSCustomControl()
parameter. This parameter, valueP
, is declared as a void *
so you can pass a pointer to a structure of any type. A second parameter, valueLenP
, allows you to specify the length of valueP
. Note that these values are simply passed to the file system and are in reality dependent upon the underlying file system. See the description of VFSCustomControl()
in Chapter 8, "VFS Manager," for more information.
Because VFSCustomControl()
is designed to allow access to non-standard functionality provided by a particular file system, see the documentation provided with that file system for a list of any custom functions that it provides.
Custom I/O
While the Expansion and VFS Managers provide higher-level OS support for secondary storage applications, they don't attempt to present anything more than a raw interface to custom I/O applications. Since it isn't really possible to envision all uses of an expansion mechanism, the Expansion and VFS Managers simply try to get out of the way of custom hardware.
The Expansion Manager provides insertion and removal notification and can load and unload drivers. Everything else is the responsibility of the application developer. PalmSource has defined a block device driver API which is extensible by licensees. This API is designed to support all of the needs of the Expansion Manager, the VFS Manager, and the file system libraries. Applications that need to communicate with an I/O device, however, may need to go beyond the provided APIs. Such applications should wherever possible use the custom()
call, which provides direct access to the block device driver. See the documentation provided to licensees for more information on block device drivers and the custom()
call. For documentation on functions made available by a particular I/O device, along with how you access those functions, contact the I/O device manufacturer.