00001 /***************************************************************************** 00002 * 00003 * $RCSfile: getdir_8c-source.html,v $ 00004 * 00005 * 00006 * Store "directory" of a set of databases / files 00007 * in 3 different databases (see parameters). 00008 * 00009 * History: 00010 * 2002-12-23: first version, taken from the ZBoxZ application suite 00011 * (Rev. 0.30) by Tom Zerucha 00012 * 00013 * This program is Copyright (C) 12/2002 Matthias Prinke 00014 * <matthias.prinke@surfeu.de> and covered by GNU's GPL. 00015 * In particular, this program is free software and comes WITHOUT 00016 * ANY WARRANTY. 00017 * 00018 * $Author: mp $ 00019 * 00020 * $Date: 2007-10-08 20:40:33 $ 00021 * 00022 * $Revision: 1.7.2.1 $ 00023 * 00024 * $Log: getdir_8c-source.html,v $ 00024 * Revision 1.7.2.1 2007-10-08 20:40:33 mp 00024 * updated for gps4palm V0.9.5 beta 00024 * 00025 * Revision 1.5 2005-02-26 14:50:23 mp 00026 * removed debug output 00027 * 00028 * Revision 1.4 2005/02/19 14:34:33 mp 00029 * removed #include <Unix/sys_types.h> (now included in stringil.h) 00030 * 00031 * Revision 1.3 2005/02/19 11:15:11 mp 00032 * added getdir_vfs(), modified name/creator of scratchpad DB 00033 * 00034 * Revision 1.2 2003/11/23 19:57:30 mp 00035 * moved CreateDatabase and DestroyDatabase from FileselForm.c 00036 * 00037 * Revision 1.1 2003/10/18 16:25:21 mp 00038 * imported from piv 00039 * 00040 * 00041 * 00042 ****************************************************************************/ 00043 00044 #include <PalmOS.h> 00045 #include <PalmCompatibility.h> 00046 #include <Extensions/ExpansionMgr/VFSMgr.h> 00047 #include "stringil.h" 00048 #include "getdir.h" 00049 #include "common.h" 00050 00051 //#define VERBOSE 00052 00053 00054 /****************************************************************************/ 00055 /** 00056 * \brief Store "directory" of a set of databases (i.e. files) 00057 * in 3 different database records. 00058 * <pre> 00059 * filelist < size0 (4 bytes) >< filename0 > 00060 * < size1 (4 bytes) >< filename1 > 00061 * ... 00062 * filecard < card0 > (card of 1st file) 00063 * < card1 > (card of 2nd file) 00064 * ... 00065 * filelp < ptr0 > (pointer to 1st filelist entry) 00066 * < ptr1 > (pointer to 2nd filelist entry) 00067 * ... 00068 * </pre> 00069 * \param filelist start of filelist record 00070 * \param filecard filecard record 00071 * \param filelp filelp record 00072 * 00073 * \return Total number of files. 00074 ****************************************************************************/ 00075 UInt16 getdir(char *filelist, char *filecard, char **filelp) 00076 { 00077 UInt16 cardno; /* card no. */ 00078 UInt32 card; /* card no. and File Streaming Flag */ 00079 UInt16 attr; /* attributes */ 00080 UInt32 type; /* type ID */ 00081 UInt32 crea; /* creator ID */ 00082 UInt32 ndb; /* number of databases on current card */ 00083 UInt32 size; /* size (payload) */ 00084 UInt32 i; /* index (database, list) */ 00085 UInt32 j; /* offset within record */ 00086 UInt32 tmp; /* start position of file suffix */ 00087 UInt32 *flpt; /* file list pointer */ 00088 UInt32 *fl; /* file list pointer */ 00089 UInt32 disp; /* displacement in filelist */ 00090 UInt16 maxrow; /* total number of rows (files) */ 00091 UInt16 n; /* y-position of WinDrawChars() */ 00092 Char tp[44]; /* temporary filelist buffer */ 00093 LocalID lid; /* local database ID */ 00094 00095 maxrow = 0; 00096 disp = 0; 00097 n = 15; 00098 00099 #ifdef VERBOSE 00100 WinDrawChars("Getting Directory...", 20, 0, 0); 00101 #endif 00102 00103 /* search files on all cards */ 00104 for (cardno = 0; cardno < MemNumCards(); cardno++) { 00105 ndb = DmNumDatabases(cardno); 00106 j = maxrow; 00107 fl = flpt = MemPtrNew(ndb * 4); 00108 00109 /* search all files on current card */ 00110 for (i = 0; i < ndb; i++) { 00111 memset(tp, 0, SORTPREFIX); /* for robustness, if sortprefix is >4, and the sort opt is smaller */ 00112 lid = DmGetDatabase(cardno, i); 00113 DmDatabaseInfo(cardno, lid, &tp[SORTPREFIX], &attr, NULL, NULL, NULL, 00114 NULL, NULL, NULL, NULL, &type, &crea); 00115 /* check type and attributes: only file streams of type data are valid */ 00116 if (!(attr & dmHdrAttrStream) || type != 'DATA') 00117 continue; 00118 00119 /* check creator ID: only 'BOXR' is valid */ 00120 if (crea != 'BOXR') 00121 continue; 00122 00123 /* check filename suffix: only GIF and PNG valid */ 00124 tmp = StrLen(&tp[SORTPREFIX]) - 4; 00125 if ( (StrCaselessCompare(&tp[SORTPREFIX + tmp], ".gif") != 0) && 00126 (StrCaselessCompare(&tp[SORTPREFIX + tmp], ".png") != 0) ) 00127 continue; 00128 00129 #ifdef VERBOSE 00130 WinDrawChars(&tp[SORTPREFIX], StrLen(&tp[SORTPREFIX]), 0, n); 00131 n += 12; 00132 #endif 00133 00134 /* 00135 * Copy type, creator, size, i, backup/creation/modification date, 00136 * or nrecs into tp (4 bytes) for alternate sorting 00137 * (only using payload size here) 00138 */ 00139 DmDatabaseSize(cardno, lid, NULL, NULL, &size); 00140 memcpy(tp, &size, 4); 00141 #ifdef VERBOSE 00142 { 00143 char t[10]; 00144 StrIToA(t, *tp); 00145 WinDrawChars(t, StrLen(t), 0, n); 00146 n += 12; 00147 } 00148 #endif 00149 00150 /* 00151 * Write file list DB 00152 * Each entry consists of a <size><filename> pair. 00153 * While the <size> entry always has 4 bytes, the 00154 * filename has a variable length. 00155 */ 00156 DmWrite( filelist, /* recordP: file list */ 00157 disp, /* offset: see below */ 00158 tp, /* srcP: pointer to <size><name> entry */ 00159 strlen(&tp[SORTPREFIX]) + SORTPREFIX + 1 /* bytes */ 00160 ); 00161 00162 card = cardno | FS_FLAG; 00163 00164 /* write card number to filecard */ 00165 DmWrite(filecard, /* recordP: filecard */ 00166 maxrow * 4, /* offset */ 00167 &card, /* srcP */ 00168 4 /* bytes */ 00169 ); 00170 00171 /* fl: array of pointers to file list entries */ 00172 *fl++ = (UInt32) filelist + disp; 00173 00174 /* calculate offset (displacement) for next file list entry */ 00175 disp += strlen(&tp[SORTPREFIX]) + SORTPREFIX + 1; 00176 00177 /* increment total number of rows (= files) on all cards */ 00178 maxrow++; 00179 } /* for (i = 0; i < ndb; i++) */ 00180 00181 /* 00182 * Write file list pointer DB 00183 * Each entry consists of a pointer to a file list entry (4 bytes). 00184 * All entries for the current card are written as a block. 00185 */ 00186 DmWrite( filelp, /* recordP: file list pointers */ 00187 j * 4, /* offset: number of files on prev. cards x (4 bytes) */ 00188 flpt, /* srcP: array of file pointers fo current card */ 00189 (maxrow - j) * 4); /* bytes: number of files on current card 00190 x (4 bytes) */ 00191 00192 /* Deallocate array of file pointers */ 00193 MemPtrFree(flpt); 00194 } /* for (cardno = 0; cardno < MemNumCards(); cardno++) */ 00195 00196 return maxrow; 00197 } 00198 00199 00200 /****************************************************************************/ 00201 /** 00202 * \brief Store directory on external memory cards (VFS) 00203 * in 3 different database records. 00204 * <pre> 00205 * filelist < size0 (4 bytes) >< filename0 > 00206 * < size1 (4 bytes) >< filename1 > 00207 * ... 00208 * filecard < vol0 > (volume of 1st file) 00209 * < vol1 > (volume of 2nd file) 00210 * ... 00211 * filelp < ptr0 > (pointer to 1st filelist entry) 00212 * < ptr1 > (pointer to 2nd filelist entry) 00213 * ... 00214 * </pre> 00215 * \param filelist start of filelist record 00216 * \param filecard filecard record 00217 * \param filelp filelp record 00218 * \param files number of files already found 00219 * (File Streaming API) 00220 * 00221 * \return Total number of files. 00222 ****************************************************************************/ 00223 UInt16 getdir_vfs(char *filelist, char *filecard, char **filelp, UInt16 files) 00224 { 00225 UInt16 volRefNum; /* VFS volume reference number */ 00226 UInt32 volIterator; /* VFS volume iterator */ 00227 FileRef dirRef; /* directory reference */ 00228 FileRef fileRef; /* file reference */ 00229 UInt32 card; /* card/volume number */ 00230 UInt32 size; /* file size */ 00231 UInt16 file_cnt; /* file counter */ 00232 UInt32 flp; /* ptr to filelist entry (typecasted) */ 00233 UInt32 tmp; /* start position of file suffix */ 00234 UInt32 disp; /* displacement in filelist */ 00235 UInt16 n; /* y-position of WinDrawChars() */ 00236 Err err; /* error code */ 00237 00238 n = 15; 00239 file_cnt = files; 00240 00241 /* find end of records */ 00242 if (file_cnt > 0) { 00243 disp = (UInt32)(filelp[files-1]) - (UInt32)*filelp ; 00244 disp += StrLen(filelp[files-1] + SORTPREFIX) + SORTPREFIX + 1; 00245 flp = (UInt32)filelist + disp; 00246 } else { 00247 disp = 0; 00248 flp = (UInt32)filelist; 00249 } 00250 00251 #ifdef VERBOSE 00252 { 00253 Char tmp[40]; 00254 00255 StrCopy(tmp, "Getting VFS Directory..."); 00256 WinDrawChars(tmp, StrLen(tmp), 0, 0); 00257 } 00258 #endif 00259 00260 volIterator = vfsIteratorStart; 00261 00262 /* Iterate through all VFS volumes */ 00263 while (volIterator != vfsIteratorStop) { 00264 err = VFSVolumeEnumerate(&volRefNum, &volIterator); 00265 00266 if (err == errNone) { 00267 00268 /* Open the directory and iterate through the files in it. */ 00269 err = VFSFileOpen(volRefNum, FILEDIR, vfsModeRead, &dirRef); 00270 00271 if (err == errNone) { 00272 UInt32 fileIterator; 00273 FileInfoType fileInfo; 00274 Char fileName[FILENAMEMAXLEN]; 00275 MemPtr pathName; 00276 00277 fileInfo.nameP = fileName; 00278 fileInfo.nameBufLen = sizeof(fileName); 00279 fileIterator = expIteratorStart; 00280 00281 /* Iterate through all the files in the open directory */ 00282 while (fileIterator != expIteratorStop) { 00283 /* Get the next file */ 00284 err = VFSDirEntryEnumerate(dirRef, &fileIterator, &fileInfo); 00285 00286 if (err == errNone) { 00287 /* Process the file */ 00288 00289 /* filter filename suffix */ 00290 tmp = StrLen(fileInfo.nameP) - 4; 00291 if ( (StrCaselessCompare(&fileInfo.nameP[tmp], ".gif") != 0) && 00292 (StrCaselessCompare(&fileInfo.nameP[tmp], ".png") != 0) ) 00293 continue; 00294 00295 #ifdef VERBOSE 00296 WinDrawChars(fileInfo.nameP, StrLen(fileInfo.nameP), 0, n); 00297 n += 12; 00298 #endif 00299 00300 /* generate absolute file path */ 00301 pathName = MemPtrNew(sizeof(FILEDIR) + StrLen(fileInfo.nameP) + 2); 00302 StrCopy(pathName, FILEDIR); 00303 StrCat(pathName, "/"); 00304 StrCat(pathName, fileInfo.nameP); 00305 00306 /* open file to get size */ 00307 err = VFSFileOpen(volRefNum, pathName, vfsModeRead, &fileRef); 00308 00309 if (!err) { 00310 err = VFSFileSize(fileRef, &size); 00311 00312 if (err) { 00313 size = 0; 00314 } 00315 VFSFileClose(fileRef); 00316 } 00317 MemPtrFree(pathName); 00318 00319 /* write file size to filelist */ 00320 DmWrite(filelist, /* recordP: file list */ 00321 disp, /* offset */ 00322 &size, /* srcP: pointer to size */ 00323 sizeof(size) /* bytes (4) */ 00324 ); 00325 disp += sizeof(size); 00326 00327 /* write file name to filelist */ 00328 DmWrite(filelist, /* recordP: filelist */ 00329 disp, /* offset */ 00330 fileInfo.nameP, /* srcP: pointer to file name */ 00331 StrLen(fileInfo.nameP) + 1 /* bytes */ 00332 ); 00333 disp += StrLen(fileInfo.nameP) + 1; 00334 00335 /* volume/card reference number */ 00336 card = volRefNum | VFS_FLAG; 00337 00338 /* write volume reference number to filecard */ 00339 DmWrite(filecard, /* recordP: filecard */ 00340 file_cnt * 4, /* offset */ 00341 &card, /* srcP */ 00342 4 /* bytes */ 00343 ); 00344 00345 /* write pointer to filelist entry to filelp */ 00346 DmWrite(filelp, /* recordP: filelist pointers */ 00347 file_cnt * 4, /* offset */ 00348 &flp, /* srcP */ 00349 4 /* bytes */ 00350 ); 00351 00352 /* pointer to next file list entry */ 00353 flp = (UInt32)filelist + disp; 00354 00355 /* increment file count */ 00356 file_cnt++; 00357 00358 } else { 00359 /* handle directory open error */ 00360 #ifdef VERBOSE 00361 { 00362 Char tmp[40]; 00363 00364 StrCopy(tmp, "Cannot open file: "); 00365 StrIToH(&tmp[StrLen(tmp)], err); 00366 WinDrawChars(tmp, StrLen(tmp), 0, n); 00367 n += 12; 00368 } 00369 #endif 00370 break; 00371 } 00372 00373 } /* while (fileIterator != expIteratorStop) */ 00374 00375 err = VFSFileClose(dirRef); 00376 00377 00378 } else { 00379 /* handle error... */ 00380 00381 #ifdef VERBOSE 00382 { 00383 Char tmp[40]; 00384 00385 StrCopy(tmp, "Cannot open directory: "); 00386 StrIToH(&tmp[StrLen(tmp)], err); 00387 WinDrawChars(tmp, StrLen(tmp), 0, n); 00388 n += 12; 00389 } 00390 #endif 00391 break; 00392 } 00393 } 00394 } /* while (volIterator != vfsIteratorStop) */ 00395 00396 return file_cnt; 00397 } 00398 00399 00400 /****************************************************************************/ 00401 /** 00402 * \brief Create scratchpad database with 3 records. 00403 * 00404 * 00405 * \note All parameters are returned 'by reference', because the memory 00406 * locations of the database records are determined by this 00407 * function. 00408 * 00409 * \param ref pointer to database reference 00410 * \param filelist pointer to start of filelist record 00411 * \param filecard pointer to filecard record 00412 * \param filelp pointer to filelp record 00413 * 00414 ****************************************************************************/ 00415 void CreateDatabase(DmOpenRef *ref, 00416 char **filelist, char **filecard, char ***filelp) 00417 { 00418 LocalID lid; /* local database ID */ 00419 DmOpenRef scratch; /* scratchpad DB reference */ 00420 MemHandle hand; /* DB record memory handle */ 00421 UInt16 dbrec = 0; /* index of new record */ 00422 00423 /* open/create scratchpad database */ 00424 lid = DmFindDatabase(0, "GPS4PALMSCRATCHPAD"); 00425 if (!lid) { 00426 DmCreateDatabase(0, "GPS4PALMSCRATCHPAD", kCreatorId, 'DATA', false); 00427 lid = DmFindDatabase(0, "GPS4PALMSCRATCHPAD"); 00428 } 00429 scratch = DmOpenDatabase(0, lid, dmModeReadWrite); 00430 00431 if (!scratch) 00432 ErrDisplay("Could not access scratchpad!"); 00433 00434 hand = DmNewRecord(scratch, &dbrec, FILELISTRECORDSIZE); 00435 *filelist = MemHandleLock(hand); 00436 hand = DmNewRecord(scratch, &dbrec, FILELPRECORDSIZE); 00437 *filelp = MemHandleLock(hand); 00438 hand = DmNewRecord(scratch, &dbrec, FILECARDRECORDSIZE); 00439 *filecard = MemHandleLock(hand); 00440 00441 *ref = scratch; 00442 } 00443 00444 00445 /****************************************************************************/ 00446 /** 00447 * \brief Remove all records and close scratchpad database 00448 * 00449 * \param ref database reference 00450 * \param filelist start of filelist record 00451 * \param filecard filecard record 00452 * \param filelp filelp record 00453 * 00454 ****************************************************************************/ 00455 void DestroyDatabase(DmOpenRef ref, 00456 char *filelist, char *filecard, char **filelp) 00457 { 00458 MemPtrUnlock(filelp); 00459 MemPtrUnlock(filecard); 00460 MemPtrUnlock(filelist); 00461 00462 /* remove all records from scratchpad DB */ 00463 while (DmNumRecords(ref)) 00464 DmRemoveRecord(ref, 0); 00465 00466 /* close scratchpad DB */ 00467 DmCloseDatabase(ref); 00468 }