November 25, 2014
Hot Topics:

How Palm OS Expands Your Applications: Files and Folders

  • June 8, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

The next option to be considered is to place your data files under the "/PALM/Launcher" folder so they can be automatically loaded into RAM from an expansion card, together with your application. Such databases, called "bundled databases," require a dmHdrAttrBundle flag to be set. They are removed from main memory at the moment user exits your application or switches to another one. Bundled databases are intended for read-only access because they aren't copied back to the card. From the other side, all databases created by your applicaition in main memoty will remain there after the application itself exits. At the next run, you can use such data without any problem.

And, finally, you have the way to manually transfer native Palm databases between an expansion card and main memory. Moreover, Palm OS provides you with the means to display the progress of the operation while doing so.

Err VFSImportDatabaseFromFile(UInt16 volRefNum,
                              const Char *pathNameP,
                              UInt16 *cardNoP, LocalID *dbIDP)

Err VFSImportDatabaseFromFileCustom(UInt16 volRefNum,
                                    const Char *pathNameP,
                                    UInt16 *cardNoP, LocalID *dbIDP,
                                    VFSImportProcPtr importProcP,
                                    void *userDataP)

Err VFSExportDatabaseToFile(UInt16 volRefNum, const Char *pathNameP,
                            UInt16 cardNo, LocalID dbID)

Err VFSExportDatabaseToFileCustom(UInt16 volRefNum,
                                  const Char *pathNameP,
                                  UInt16 cardNo, LocalID dbID,
                                  VFSExportProcPtr exportProcP,
                                  void *userDataP)

These two pairs of functions do opposite moves: The first ones copy data from the expansion card into main memory while the second pair converts database from its internal Palm OS format into equivalent PDB or PRC and transfers it to expansion card. 'Custom' functions takes callback as one of the parameters, so you can inform the user about operation progress. All these functions use Exchange Manager technique to copy data from source to destination. It means that, for example, VFSExportDatabaseToFileCustom internally calls ExgWriteDB and provides its own callback to copy data. I'll put here a shortened excerpt from the attached code sample to illustrate the exporting custom process:

struct UserData
   const char *szFileName;
   ProgressType* pProgressBar;

static Boolean CallbackFunc(PrgCallbackDataPtr cbP)
   const char* szName = ((UserData*)(cbP->userDataP))->szFileName;
   if ( cbP->stage == 0 )
      StrPrintF(cbP->textP,"Exporting Database %s",szName);
      StrPrintF(cbP->textP,"Exporting Database %s: %d%%",szName,
   cbP->textChanged = true;

   return true;

static Err VFSExportCustomProc(UInt32 totalBytes, UInt32 offset,
                               void *userDataP)
   UserData* pData = (UserData*)userDataP;
   if ( offset == 0 )
      pData->pProgressBar =
         PrgStartDialog("Exporting Database",CallbackFunc,pData);

      if ( pData->pProgressBar )
         return errNone;
         return memErrNotEnoughSpace;


   EventType event;
   Boolean handled;
      handled = PrgHandleEvent(pData->pProgressBar,&event);
      if ( !handled )
         if ( PrgUserCancel(pData->pProgressBar) )
            return exgErrUserCancel;
   while (event.eType != sysEventNilEvent);

   return errNone;

Boolean CMainForm::OnExportCustom(EventPtr pEvent,
                                  Boolean& bHandled)

   Err err;
   LocalID dbID = 0;
   CString sLine;
   CDatabase DB;
   err = DB.OpenOrCreate(0,(const char*)m_sPDBName,'ALEX','data');
   for (int i = 0; i < 1000; i++)
      sLine.Format("Line #%d",i);
      CRecordStream rs(&DB);
      rs << sLine;


   UInt16 volRefNum = -1;
   UInt32 volIterator = vfsIteratorStart;

   CString sInfo;
   while ( volIterator != vfsIteratorStop )
      err = VFSVolumeEnumerate(&volRefNum, &volIterator);
      if (err == errNone)
         VolumeInfoType volInfo;
         err = VFSVolumeInfo(volRefNum,&volInfo);
         sInfo.Format("Attr: %lu, Type: %s, Class = %s,
                      MediaType = %s", volInfo.attributes,
                      (const char*)GetFileSystemType(volInfo.fsType),
                      (const char*)GetMountClass(volInfo.mountClass),
                      (const char*)GetMediaType(volInfo.mediaType));
                      DDX_Text(&m_fldDescription, sInfo,
         // handle the error

   char szFileName[256];
   StrPrintF(szFileName,"/%s",(const char*)m_sFileName);
   UserData userData;
   userData.szFileName = szFileName;
   userData.pProgressBar = NULL;
   err = VFSExportDatabaseToFileCustom(volRefNum,(const char*)
   if ( userData.pProgressBar )
      PrgStopDialog(userData.pProgressBar,(err == exgErrUserCancel));

   return true;

This sample application creates a PDB into main memory with 1000 text lines and then exports it to the very first available mounted volume. The code snippet shows various aspects of VFS Manager programming: volume enumeration, getting info, displaying progress bar, and so forth. Similar code will import data from the expansion card to main memory. The sample uses a POL library to make life easier, but I guess this won't disturb you in catching the main idea.


On this optimistic note, you will have a break with VFS Manager. As you can see, all the stuff is relatively simple and works really well. From the other side, it gives you a powerful mechanism to manage a large amount of data without making too big an effort. I hope this series will help you understand all black niches of the VFS Manager API. In the next article, you will continue to investigate this area and talk about Expansion Manager capabilities.

Download the Source Code

Download the accompanying code's zip file here

About the Author

Alex Gusev started to play with mainframes in the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.

Page 2 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel