contentLister/src/erMdsFs.c File Reference

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <linux/limits.h>
#include <sys/vfs.h>
#include <glib/gprintf.h>
#include <gtk/gtk.h>
#include <libermanifest/ermanifest.h>
#include "contentListerLog.h"
#include "erConnect.h"
#include "system.h"
#include "gtkPincodeScreen.h"
#include "control.h"
#include "erMdsContent.h"
#include "languages.h"
#include "metadataStoreManager.h"

Go to the source code of this file.

Classes

struct  trusted_device_t

Defines

#define MOBIPOCKET_CHECK1_OFFSET   0x3C
#define MOBIPOCKET_FIRST_RECORD   0x4E
#define MOBIPOCKET_CHECK2_OFFSET   0x10
#define MOBIPOCKET_ENCODING_OFFSET   0x1C
#define MOBIPOCKET_CHECK3_OFFSET   0x24
#define MOBIPOCKET_TITLE_RECORD_OFFSET   0x54
#define MOBIPOCKET_TITLE_LENGTH_OFFSET   0x58
#define MOBIPOCKET_PDB_TITLE_OFFSET   0x00
#define MOBIPOCKET_PDB_TITLE_LENGTH   0x20
#define MOBIPOCKET_ENCODING_UTF8   0xFDE9
#define MOBIPOCKET_ENCODING_WIN1252   0x04E4

Functions

static int erClGetFileType (const char *szPath)
static int erClGetSymlinkInfo (const char *szRealpath, mdsFsItemType_e *pFit)
static void mdsContentPreSort (GArray *contentItemArray, mdsSortStruct_t *sort)
static void mdsContentPostSort (GArray *contentItemArray)
static gint mdsFieldFsNameComparison (gconstpointer a, gconstpointer b, gpointer user_data)
static gint mdsFieldGenericComparison (gconstpointer a, gconstpointer b, gpointer user_data)
static int datecmp (const char *dateA, const char *dateB)
static int sizecmp (const char *sizeA, const char *sizeB)
static void mdsFetchField (mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char *szField)
static void mdsFetchFieldOfFile (mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char *szField)
static void mdsFetchFieldOfFolder (mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char *szField)
static void mdsFetchFieldOfContainer (mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char *szField)
static void mdsFetchFieldOfSymlink (mdsFsItem_t *pFsItem, mdsSortStruct_t *sort, char *szField)
static void getFakeTitle (const char *szPath, char *szTitle)
static int getSize (const char *pathName)
static void getDate (const char *szPath, char *szDate)
static void getExtName (const char *szPath, char *szExt)
static gboolean getMobipocketTitle (const char *szPath, char *szTitle)
static gboolean is_mobipocket_folder (const char *szPath, const int len)
static void displayItemSetDefault (clDisplayItem_t *displayItem)
static void containerGetDisplayItem (mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
static void symlinkGetDisplayItem (mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
static void fileGetDisplayItem (mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
static void folderGetDisplayItem (mdsFsItem_t *pFsItem, clDisplayItem_t *displayItem)
static gboolean extensionIsMobipocket (char *pExt)
const gchar * ctrl_is_trusted_path (const char *path)
int erMdsContentScan (GArray *dirArray, GArray **contentItemArray)
int erMdsContentSort (GArray *contentItemArray, mdsSortStruct_t *sort)
int erClGetDisplayItems (GArray *contentItemArray, int nBegin, int *nChunk, clDisplayItem_t *displayItemArray)

Variables

static trusted_device_t g_trusted_devices []


Define Documentation

#define MOBIPOCKET_CHECK1_OFFSET   0x3C

Copyright (C) 2005-2008 iRex Technologies B.V. All rights reserved.

Definition at line 52 of file erMdsFs.c.

#define MOBIPOCKET_CHECK2_OFFSET   0x10

Definition at line 54 of file erMdsFs.c.

#define MOBIPOCKET_CHECK3_OFFSET   0x24

Definition at line 56 of file erMdsFs.c.

#define MOBIPOCKET_ENCODING_OFFSET   0x1C

Definition at line 55 of file erMdsFs.c.

#define MOBIPOCKET_ENCODING_UTF8   0xFDE9

Definition at line 62 of file erMdsFs.c.

#define MOBIPOCKET_ENCODING_WIN1252   0x04E4

Definition at line 63 of file erMdsFs.c.

#define MOBIPOCKET_FIRST_RECORD   0x4E

Definition at line 53 of file erMdsFs.c.

#define MOBIPOCKET_PDB_TITLE_LENGTH   0x20

Definition at line 60 of file erMdsFs.c.

#define MOBIPOCKET_PDB_TITLE_OFFSET   0x00

Definition at line 59 of file erMdsFs.c.

#define MOBIPOCKET_TITLE_LENGTH_OFFSET   0x58

Definition at line 58 of file erMdsFs.c.

#define MOBIPOCKET_TITLE_RECORD_OFFSET   0x54

Definition at line 57 of file erMdsFs.c.


Function Documentation

static void containerGetDisplayItem ( mdsFsItem_t pFsItem,
clDisplayItem_t displayItem 
) [static]

Definition at line 1614 of file erMdsFs.c.

01615 {
01616     char*   cp = NULL;
01617     char    szFilename[ERMDS_MAX_FILENAME_SIZE];
01618     char    szRealpath[PATH_MAX];
01619     char    szManifestPath[ERMDS_MAX_FILENAME_SIZE];
01620     char    storageDirName[ERMDS_MAX_FILENAME_SIZE];
01621     int     nPathLength;
01622     int     ret;
01623     struct stat   statbuf;
01624     struct statfs statfsbuf;
01625     st_ContentType_e storageType;
01626     mdsFsItem_t fsItemSymlink;
01627 
01628     static int  nSymlinkChain = 0;
01629     
01630     if (NULL == pFsItem || pFsItem->fit != mdsFitContainer || NULL == displayItem)
01631     {
01632         CL_ERRORPRINTF("invalid arguments");
01633         return;
01634     }
01635 
01636     // Convert symlinks into the real path
01637     // Note: also needed for symlinks in directory path, e.g. /opt/content/books/...
01638     cp = realpath(pFsItem->szFilename, szRealpath);
01639     if (cp != NULL)
01640     {
01641          CL_LOGPRINTF("entry %s", szRealpath);
01642          snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01643     }
01644     else
01645     {
01646         CL_LOGPRINTF("entry %s", pFsItem->szFilename);
01647         strcpy(szFilename, pFsItem->szFilename);
01648     }
01649    
01650     // fit = filesystem item type
01651     displayItem->fit = pFsItem->fit;
01652 
01653     // A container is a directory containing a manifest file
01654     nPathLength = g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, szFilename);
01655     if (   stat(szManifestPath, &statbuf) == 0
01656         && S_ISREG(statbuf.st_mode)           )
01657     {
01658         // Store Manifest file
01659         strcpy(displayItem->szManifest, szManifestPath);
01660 
01661         // Manifest file exists: parse the manifest file
01662         // Note: function erClXmlParseManifest() may change displayItem->fit and ->szManifest
01663         ret = erClXmlParseManifest(szFilename, displayItem);
01664 
01665         if (ret == 0)
01666         {
01667             switch (displayItem->fit)
01668             {
01669                 case mdsFitContainer:
01670                     // normal container: determine the file extension (of the start page)
01671                     getExtName(displayItem->szFilename, displayItem->szFileExt);
01672                     if (0 == strlen(displayItem->szFileExt))
01673                     {
01674                         CL_WARNPRINTF("%s does not have a file extension", szFilename);
01675                     }
01676                     if (displayItem->size <= 0)
01677                     {
01678                         // write the size of container to manifest.xml
01679                         displayItem->size = getSize(szFilename);
01680                         erClXmlSetFieldSize(szFilename, displayItem->size);    
01681                     }
01682                     break;
01683                     
01684                 case mdsFitStorage:
01685                     // storage device: get free space when possible
01686                     storageType = ctrl_get_storageType(displayItem->szExtID);
01687                     if (   stackIsStorage(storageType)
01688                         && storageIsMounted(storageType)
01689                         && mdsGetRootLocation(storageType, storageDirName, sizeof(storageDirName)) > 0 )
01690                     {
01691                         if (statfs(storageDirName, &statfsbuf) == 0)
01692                         {
01693                             displayItem->size = statfsbuf.f_bavail * statfsbuf.f_bsize / 1024;
01694                         }
01695                     }
01696                     break;
01697 
01698                 case mdsFitManifestSymlinkLocale:
01699                     // Use locale-specific directory, if present.
01700                     snprintf( szFilename, sizeof(szFilename),
01701                               "%s/.%s",
01702                               displayItem->szFilename,
01703                               languagesGetLocale()    );
01704                     if ( stat(szFilename, &statbuf) == 0 )
01705                     {
01706                         strcpy(displayItem->szFilename, szFilename);
01707                     }
01708                     else
01709                     {
01710                         snprintf( szFilename, sizeof(szFilename),
01711                                   "%s/.%s",
01712                                   displayItem->szFilename,
01713                                   DEFAULT_LOCALE          );
01714                         if ( stat(szFilename, &statbuf) == 0 )
01715                         {
01716                             strcpy(displayItem->szFilename, szFilename);
01717                         }
01718                         else
01719                         {
01720                             CL_WARNPRINTF("not found [%s]", szFilename);
01721                             // downgrade to folder item
01722                             fsItemSymlink     = *pFsItem;
01723                             fsItemSymlink.fit = mdsFitFolder;
01724                             strcpy(fsItemSymlink.szFilename, displayItem->szFilename);
01725                             folderGetDisplayItem(&fsItemSymlink, displayItem);
01726                             break;  // exit switch, NO FALLTHROUGH
01727                         }
01728                     }
01729                     // FALLTHROUGH to case mdsFitManifestSymlink
01730 
01731                 case mdsFitManifestSymlink:
01732                     if (nSymlinkChain < ERMDS_MAX_SYMLINK_CHAIN)
01733                     {
01734                         nSymlinkChain++;
01735                         // simulate an FsItem for a symbolic link at filesystem level
01736                         fsItemSymlink     = *pFsItem;
01737                         fsItemSymlink.fit = mdsFitSymlink;
01738                         strcpy(fsItemSymlink.szFilename, displayItem->szFilename);
01739                         // get details for symlink, or leave displayItem unchanged
01740                         symlinkGetDisplayItem(&fsItemSymlink, displayItem);
01741                         nSymlinkChain--;
01742                     }
01743                     else
01744                     {
01745                         CL_ERRORPRINTF("Symlink chain too long for [%s]", displayItem->szFilename);
01746                         ret = -1;
01747                     }
01748                     break;
01749 
01750                 default:
01751                     if (displayItem->iconID == clUnknownIcon)
01752                     {
01753                         displayItem->iconID = clFolderIcon;
01754                     }
01755             }
01756         }
01757         else
01758         {
01759             CL_ERRORPRINTF("Failure to parse %s", szManifestPath);
01760             CL_ERRORPRINTF("Downgrading %s to folder", szFilename);
01761             // szFilename
01762             strcpy(displayItem->szFilename, szFilename);
01763             // Changing 'fit' to folder
01764             displayItem->fit = mdsFitFolder;
01765             // Determine Icon
01766             displayItem->iconID = clFolderIcon;
01767             // Determine title
01768             getFakeTitle(szFilename, displayItem->szTitle);
01769         }
01770     }
01771     else
01772     {
01773         // Normally this branch will not be taken.
01774         CL_ERRORPRINTF("%s is missing. Illegal branch", szManifestPath);
01775     }
01776 }

Here is the call graph for this function:

const gchar* ctrl_is_trusted_path ( const char *  path  ) 

Definition at line 123 of file erMdsFs.c.

00124 {
00125     const gchar*       ret = NULL;  // return value
00126     trusted_device_t*  pDevice;
00127 
00128     static gboolean first_time = TRUE;
00129     static char*    download_history = NULL;  // name of the download history directory
00130     static int      download_history_len = 0;
00131 
00132 
00133     // do first-time initialisations
00134     if (first_time)
00135     {
00136         char   dirname[ERMDS_MAX_FILENAME_SIZE];
00137 
00138         // determine length for pathnames of trusted devices
00139         for (pDevice = (trusted_device_t*)&g_trusted_devices[0] ; pDevice->path != NULL ; pDevice++)
00140         {
00141             pDevice->len = strlen(pDevice->path);
00142         }
00143 
00144         // determine location of download history
00145         if (mdsGetRootLocation(st_DownloadHistory, dirname, sizeof(dirname)) > 0)
00146         {
00147             download_history     = strdup(dirname);
00148             download_history_len = strlen(download_history);
00149         }
00150 
00151         // first time happens only once ;-)
00152         first_time = FALSE;
00153     }
00154     
00155     // check path in trusted devices
00156     for (pDevice = &g_trusted_devices[0] ; pDevice->path != NULL && ret == NULL ; pDevice++)
00157     {
00158         if (strncmp(path, pDevice->path, pDevice->len) == 0)
00159         {
00160             // found
00161             ret = pDevice->path;
00162         }
00163     }
00164 
00165     // if not found, check for download history
00166     if (ret == NULL  &&  download_history)
00167     {
00168         if (strncmp(path, download_history, download_history_len) == 0)
00169         {
00170             // found
00171             ret = download_history;
00172         }
00173     }
00174 
00175     // return what we found
00176     return ret;
00177 }

Here is the call graph for this function:

static int datecmp ( const char *  dateA,
const char *  dateB 
) [static]

Definition at line 592 of file erMdsFs.c.

00593 {   
00594    struct tm tmA, tmB;
00595    time_t timeA, timeB;
00596    double diff = 0;
00597    char   *string = NULL;
00598 
00599    CL_LOGPRINTF("entry");
00600 
00601    if (NULL == dateA || NULL == dateB)
00602    {
00603         CL_ERRORPRINTF("invalid arguments");
00604         return diff;
00605    }
00606    
00607    string = strptime(dateA, "%Y-%m-%dT%H:%M:%S", &tmA);
00608    string = strptime(dateB, "%Y-%m-%dT%H:%M:%S", &tmB);
00609    timeA = mktime(&tmA); 
00610    timeB = mktime(&tmB);
00611    diff = difftime(timeA, timeB);
00612 
00613    return (int)diff;
00614 }

static void displayItemSetDefault ( clDisplayItem_t displayItem  )  [static]

Definition at line 1508 of file erMdsFs.c.

01509 {
01510     if (NULL == displayItem)
01511     {
01512         return;
01513     }
01514     displayItem->iconID = clUnknownIcon;
01515     strcpy(displayItem->clIconURL, "");
01516     strcpy(displayItem->szFileExt, "");
01517     strcpy(displayItem->szTitle, "");
01518     strcpy(displayItem->szSubTitle, "");
01519     strcpy(displayItem->szDate, "");
01520     strcpy(displayItem->szDescription, "");
01521     strcpy(displayItem->szFilename, "");
01522     strcpy(displayItem->szManifest, "");
01523     displayItem->size = ERCL_INVALID_SIZE;
01524     displayItem->fit = mdsFitUndefined;
01525     displayItem->modifyEnable.bDefault  = TRUE;
01526     displayItem->modifyEnable.bDelete   = TRUE;
01527     displayItem->modifyEnable.bScribble = TRUE;
01528     displayItem->modifyEnable.bTagging  = TRUE;
01529 }

int erClGetDisplayItems ( GArray *  contentItemArray,
int  nBegin,
int *  nChunk,
clDisplayItem_t displayItemArray 
)

Definition at line 1449 of file erMdsFs.c.

01450 {
01451     int     nEnd = 0;
01452     int     i;
01453     int     j;
01454     mdsFsItem_t*    pFsItem;
01455 
01456     // Validate parameters
01457     if (nBegin < 0 || nBegin >= contentItemArray->len)
01458     {
01459         return ERCL_INVALID_ARGS;
01460     }
01461     else if (*nChunk < 0)
01462     {
01463         return ERCL_INVALID_ARGS;
01464     }
01465 
01466     nEnd = (contentItemArray->len - 1 <= nBegin + *nChunk - 1) ? contentItemArray->len - 1 : nBegin + *nChunk - 1;
01467     *nChunk = nEnd - nBegin + 1;
01468 
01469     // i counts displayItemArray items
01470     // j counts contentItemArray items
01471     for (i = 0, j = nBegin; i < *nChunk; i++, j++)
01472     {
01473         pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, j);
01474 
01475         // set default value of displayItem
01476         displayItemSetDefault(&displayItemArray[i]);
01477         
01478         // Get information to be displayed
01479         switch (pFsItem->fit)
01480         {
01481             case mdsFitFile:            
01482                 fileGetDisplayItem(pFsItem, &displayItemArray[i]);
01483                 break;
01484 
01485             case mdsFitContainer:
01486                 containerGetDisplayItem(pFsItem, &displayItemArray[i]);
01487                 break;
01488 
01489             case mdsFitFolder:
01490                 folderGetDisplayItem(pFsItem, &displayItemArray[i]);
01491                 break;
01492 
01493             case mdsFitSymlink:
01494                 symlinkGetDisplayItem(pFsItem, &displayItemArray[i]);
01495                 break;
01496 
01497             case mdsFitStorage:
01498             case mdsFitApplication:
01499             case mdsFitManifestDirectory:
01500             default:
01501                 CL_LOGPRINTF("No action required."); // No action required.
01502         }
01503     }
01504     
01505     return ERCL_OK;
01506 }

Here is the call graph for this function:

static int erClGetFileType ( const char *  szPath  )  [static]

Definition at line 1363 of file erMdsFs.c.

01364 {
01365     struct stat statBuf;
01366     char * ext;
01367     
01368     // TODO ---- TODO ---- TODO ---- TODO
01369     // Check file extension to see if we have to ignore it
01370     // We should create a nice function and get values
01371     // from the registry. Now this is hardcoded for Mobipocket.
01372     // PLEASE FIX ME!!!
01373     ext = strrchr(szPath, '.');
01374     if (ext && strcasecmp(++ext, "mbp") == 0) 
01375     {
01376         CL_LOGPRINTF("Ignoring [%s] because it has extension [%s]", szPath, ext);
01377         return GFT_IGNORE;
01378     }
01379 
01380     if (lstat(szPath, &statBuf) == -1)
01381     {
01382         CL_ERRORPRINTF("lstat(%s) returned with error [%s]", szPath, strerror(errno));
01383         return GFT_NOSUCHFILE;
01384     }
01385     else
01386     {
01387         if (S_ISLNK(statBuf.st_mode))
01388         {
01389             return GFT_SYMLINK;
01390         }
01391         else if (S_ISDIR(statBuf.st_mode))
01392         {
01393             return GFT_DIR;
01394         }
01395         else
01396         {
01397             return GFT_FILE;
01398         }
01399     }
01400 }

static int erClGetSymlinkInfo ( const char *  szRealpath,
mdsFsItemType_e pFit 
) [static]

Definition at line 1402 of file erMdsFs.c.

01403 {
01404     int         n;
01405     char        szManifestPath[ERMDS_MAX_FILENAME_SIZE];
01406     struct stat statbuf;
01407     int         filetype;
01408     int         ret;
01409 
01410     // Default return: error
01411     ret = ERCL_NOMATCH;
01412     *pFit = mdsFitUndefined;
01413     g_assert(szRealpath != NULL);
01414 
01415     // Determine the fit and filename for symlinks
01416     filetype = erClGetFileType(szRealpath);
01417     switch (filetype)
01418     {
01419         case GFT_FILE:
01420             *pFit = mdsFitFile;
01421             ret = ERCL_OK;
01422             break;
01423 
01424         case GFT_DIR:
01425             *pFit = mdsFitFolder;
01426             ret = ERCL_OK;
01427 
01428             // If the directory contains a manifest file we have a container
01429             n = g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, szRealpath);
01430             if (n < ERMDS_MAX_FILENAME_SIZE)
01431             {
01432                 // Does the manifest file exist?
01433                 if (   stat(szManifestPath, &statbuf) == 0
01434                     && S_ISREG(statbuf.st_mode)           )
01435                 {
01436                     *pFit = mdsFitContainer;
01437                 }
01438             }
01439             break;
01440 
01441         default:
01442             CL_ERRORPRINTF("unexpected filetype [%d] for [%s]", filetype, szRealpath);
01443             ;  // ignore
01444     }
01445 
01446     return ret;
01447 }

Here is the call graph for this function:

int erMdsContentScan ( GArray *  dirArray,
GArray **  contentItemArray 
)

Scan an array of directories for content items that match search criteria.

Parameters:
dirArray An array of directories that will be scanned
contentItemArray Will contain retrieved content items. Pass NULL when you want the function to allocate memory
Returns:
one of the following errorcodes: ERMDS_CONTENT_SCAN_OK, ERMDS_CONTENT_SCAN_FAILED, ERMDS_CONTENT_SCAN_TOO_MANY_ITEMS

Definition at line 183 of file erMdsFs.c.

00184 {
00185     gint    nDir;
00186     guint   initialArraySize = ERMDS_INITIAL_CONTENT_SCAN_ARRAY_SIZE;
00187     DIR    *dirp;
00188     struct dirent *direntp;
00189     mdsFsItem_t fsItem;
00190     int     ret = ERMDS_CONTENT_SCAN_OK;
00191 
00192     CL_LOGPRINTF("entry");
00193 
00194     // Only create a new array when necessary:
00195     if (*contentItemArray == NULL)
00196     {
00197         CL_LOGPRINTF("Creating a new contentItemArray");
00198         // Create a new array for initialArraySize items to store mdsFsItem_t values.
00199         // Don't zero-terminate or clear to 0's.
00200         *contentItemArray = g_array_sized_new(FALSE, FALSE, sizeof(mdsFsItem_t), initialArraySize);
00201     }
00202 
00203     CL_LOGPRINTF("dirArray->len = %d", dirArray->len);
00204 
00205     // Loop over all directories 
00206     for (nDir = 0; nDir < dirArray->len; nDir++)
00207     {
00208         // This works because mdsDirectory_t contains the filename as first member
00209         char   *szDir = (char *) &g_array_index(dirArray, mdsDirectory_t, nDir);
00210 
00211         if ((dirp = opendir(szDir)) == NULL)
00212         {
00213             // This is not an error condition
00214             CL_WARNPRINTF("Could not open directory %s (error %s).", szDir, strerror(errno));
00215         }
00216         else
00217         {
00218             while ((direntp = readdir(dirp)) != NULL)
00219             {
00220                 // Hide '.' and '..' entries and names starting with a dot
00221                 // Hide file/dir names starting with an underscore
00222                 // Hide 'manifest.xml' files
00223                 if ((direntp->d_name[0] != (int) '.') && (direntp->d_name[0] != (int) '_')
00224                         && (strcasecmp(MANIFEST_FILENAME, direntp->d_name) != 0))
00225                 {
00226                     gint    nPathLength;
00227 
00228                     CL_LOGPRINTF("%s", direntp->d_name);
00229 
00230                     // Check on buffer overflow
00231                     nPathLength =
00232                         g_snprintf(fsItem.szFilename, ERMDS_MAX_FILENAME_SIZE, "%s/%s", szDir, direntp->d_name);
00233                     fsItem.sortField = NULL; 
00234                     fsItem.priority = 0;
00235 
00236                     if (nPathLength < ERMDS_MAX_FILENAME_SIZE)
00237                     {
00238                         // Determine the file item type: File / Container / Folder
00239                         // fprintf(stderr, "(%d)", nPathLength);
00240                         int gft = erClGetFileType(fsItem.szFilename);
00241                         switch (gft)
00242                         {
00243                             case GFT_FILE:
00244                                 fsItem.fit = mdsFitFile;
00245                                 break;
00246 
00247                             case GFT_DIR:
00248                                 {
00249                                     char        szManifestPath[ERMDS_MAX_FILENAME_SIZE];
00250                                     struct stat statbuf;
00251 
00252                                     // If the directory contains a manifest file we have a container
00253                                     g_snprintf( szManifestPath, sizeof(szManifestPath),
00254                                                               "%s/" MANIFEST_FILENAME,
00255                                                               fsItem.szFilename       );
00256                                     // Does the manifest file exist?
00257                                     if (stat(szManifestPath, &statbuf) == 0)
00258                                     {
00259                                         if (S_ISREG(statbuf.st_mode) != 0)
00260                                         {
00261                                             fsItem.fit = mdsFitContainer;
00262                                         }
00263                                         else
00264                                         {
00265                                             CL_WARNPRINTF("%s is not a regular file, default to folder type",
00266                                                           szManifestPath);
00267                                             fsItem.fit = mdsFitFolder;
00268                                         }
00269                                     }
00270                                     else
00271                                     {
00272                                         fsItem.fit = mdsFitFolder;
00273                                     }
00274                                     
00275                                     // Mobipocket HACK, sort it always on top
00276                                     if (is_mobipocket_folder(fsItem.szFilename, nPathLength))
00277                                     {
00278                                         CL_LOGPRINTF("Found Mobipocket: %s", fsItem.szFilename);
00279                                         fsItem.priority = MOBIPOCKET_FOLDER_SORT_PRIORITY;
00280                                     }
00281                                 }
00282                                 break;
00283 
00284                             case GFT_SYMLINK:
00285                                 fsItem.fit = mdsFitSymlink;
00286                                 break;
00287                                 
00288                             case GFT_NOSUCHFILE:
00289                             case GFT_IGNORE:
00290                             default:
00291                                 continue; // while ((direntp = readdir(dirp)) != NULL)
00292                         }
00293 
00294                         if ((*contentItemArray)->len < ERMDS_MAX_CONTENT_SCAN_ARRAY_SIZE)
00295                         {
00296                             g_array_append_val(*contentItemArray, fsItem);
00297                         }
00298                         else
00299                         {
00300                             ret = ERMDS_CONTENT_SCAN_TOO_MANY_ITEMS;
00301                             break;
00302                         }
00303                     }
00304                     else
00305                     {
00306                         CL_ERRORPRINTF("Filename %s/%s too long. (nPathLength (%d) > %d)", szDir, direntp->d_name,
00307                                        nPathLength, ERMDS_MAX_FILENAME_SIZE);
00308                     }
00309                 }
00310             }                   // while ((direntp = readdir(dirp)) != NULL)
00311             closedir(dirp);
00312         }
00313         if (ret == ERMDS_CONTENT_SCAN_TOO_MANY_ITEMS)
00314         {
00315             return ret;
00316         }
00317     }                           // for (nDir = 0; nDir < dirArray->len; nDir++)
00318     return ret;
00319 }

Here is the call graph for this function:

int erMdsContentSort ( GArray *  contentItemArray,
mdsSortStruct_t sort 
)

Sort the array passed as an argument according to the sort criterium.

Parameters:
contentItemArray - Contain items to be sorted
sort -
Returns:
one of the following errorcodes: ERMDS_CONTENT_SORT_OK, ERMDS_CONTENT_SORT_FAILED

Definition at line 323 of file erMdsFs.c.

00324 {
00325     int     ret;
00326     
00327     CL_LOGPRINTF("entry");
00328 
00329     switch (sort->ft)
00330     {
00331         case mdsFieldFsName:
00332             g_array_sort_with_data(contentItemArray, mdsFieldFsNameComparison, (gpointer) sort);
00333             ret = ERMDS_CONTENT_SORT_OK;
00334             break;
00335 
00336         case mdsFieldAuthor:
00337         case mdsFieldDate:
00338         case mdsFieldDescription:
00339         case mdsFieldFile:
00340         case mdsFieldTitle:
00341         case mdsFieldExtName:
00342         case mdsFieldSize:
00343             mdsContentPreSort(contentItemArray, sort);
00344             g_array_sort_with_data(contentItemArray, mdsFieldGenericComparison, (gpointer) sort);
00345             mdsContentPostSort(contentItemArray);
00346             ret = ERMDS_CONTENT_SORT_OK;
00347             break;
00348 
00349         default:
00350             CL_ERRORPRINTF("No support for sorting of type %d", (int) sort->ft);
00351             ret = ERMDS_CONTENT_SORT_NOT_IMPLEMENTED;
00352     }
00353     return ret;
00354 }

Here is the call graph for this function:

static gboolean extensionIsMobipocket ( char *  pExt  )  [inline, static]

Definition at line 114 of file erMdsFs.c.

00115 {
00116    return (gboolean) (strcasecmp(pExt, "mobi") == 0 ||
00117                         strcasecmp(pExt, "prc") == 0 ||
00118                         strcasecmp(pExt, "pdb") == 0 );
00119 }

static void fileGetDisplayItem ( mdsFsItem_t pFsItem,
clDisplayItem_t displayItem 
) [static]

Definition at line 1531 of file erMdsFs.c.

01532 {
01533     char*   cp = NULL;
01534     char    szFilename[ERMDS_MAX_FILENAME_SIZE];
01535     char    szRealpath[ERMDS_MAX_FILENAME_SIZE];
01536 
01537     // check whether arguments valid or not
01538     if (NULL == pFsItem || pFsItem->fit != mdsFitFile || NULL == displayItem)
01539     {
01540         CL_ERRORPRINTF("invalid arguments");
01541         return;
01542     }
01543     // Convert symlinks into the real path
01544     // Note: also needed for symlinks in directory path, e.g. /opt/content/books/...
01545     cp = realpath(pFsItem->szFilename, szRealpath);
01546     if (cp != NULL)
01547     {
01548          CL_LOGPRINTF("entry %s", szRealpath);
01549          snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01550     }
01551     else
01552     {
01553         CL_ERRORPRINTF("entry %s", pFsItem->szFilename);
01554         strcpy(szFilename, pFsItem->szFilename);
01555     }
01556 
01557     // szFilename   
01558     strcpy(displayItem->szFilename, szFilename);
01559     // fit
01560     displayItem->fit = pFsItem->fit;
01561     // sztitle
01562     getFakeTitle(szFilename, displayItem->szTitle);
01563     // szFileExt 
01564     getExtName(szFilename, displayItem->szFileExt);
01565     if (0 == strlen(displayItem->szFileExt))
01566     {
01567         CL_WARNPRINTF("%s does not have a file extension", szFilename);
01568     }
01569     // szDate
01570     getDate(szFilename, displayItem->szDate);
01571     // size
01572     displayItem->size = getSize(szFilename);
01573 }

Here is the call graph for this function:

static void folderGetDisplayItem ( mdsFsItem_t pFsItem,
clDisplayItem_t displayItem 
) [static]

Definition at line 1575 of file erMdsFs.c.

01576 {
01577     char*   cp = NULL;
01578     char    szFilename[ERMDS_MAX_FILENAME_SIZE];
01579     char    szRealpath[PATH_MAX];
01580 
01581     if (pFsItem == NULL || pFsItem->fit != mdsFitFolder || displayItem == NULL)
01582     {
01583         CL_ERRORPRINTF("invalid arguments");
01584         return;
01585     }
01586     // Convert symlinks into the real path
01587     // Note: also needed for symlinks in directory path, e.g. /opt/content/books/...
01588     cp = realpath(pFsItem->szFilename, szRealpath);
01589     if (cp != NULL)
01590     {
01591          CL_LOGPRINTF("entry %s", szRealpath);
01592          snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01593     }
01594     else
01595     {
01596         CL_ERRORPRINTF("entry %s", pFsItem->szFilename);
01597         strcpy(szFilename, pFsItem->szFilename);
01598     }
01599      // szFilename
01600     strcpy(displayItem->szFilename, szFilename);
01601     // fit
01602     displayItem->fit = pFsItem->fit;
01603     // Determine Title
01604     getFakeTitle(szFilename, displayItem->szTitle);
01605     // Determine Icon
01606     displayItem->iconID = clFolderIcon;
01607     // Determine date
01608     getDate(szFilename, displayItem->szDate);
01609     // determinte size
01610     //  int size = getSize(pFsItem->szFilename);
01611     //  g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
01612 }

Here is the call graph for this function:

static void getDate ( const char *  szPath,
char *  szDate 
) [static]

Definition at line 1248 of file erMdsFs.c.

01249 {
01250     struct stat statBuf;
01251 
01252     if (NULL == szPath || NULL == szDate)
01253     {
01254         CL_ERRORPRINTF("invalid arguments");
01255         return;
01256     }
01257     
01258     strcpy(szDate, "");             
01259 
01260     if (strlen(szPath))
01261     {
01262         if (stat(szPath, &statBuf) == 0)
01263         {
01264             if (S_ISREG(statBuf.st_mode) != 0 || S_ISDIR(statBuf.st_mode))
01265             {
01266                 // What is date?
01267                 struct tm localTime;
01268 
01269                 localtime_r(&statBuf.st_mtime, &localTime);
01270                 strftime(szDate, ERCL_MAX_SUBTITLE_SIZE, "%Y-%m-%dT%H:%M:%S", &localTime);
01271                 CL_LOGPRINTF("Time of %s: %s", szPath, szDate);
01272             }
01273             else if (S_ISLNK(statBuf.st_mode))
01274             {
01275                 CL_WARNPRINTF("getDate of S_ISLNK not implemented yet.");
01276             }
01277             else
01278             {
01279                 CL_WARNPRINTF("%s is not a regular file or directory", szPath);
01280             }
01281         }
01282     }
01283     else
01284     {
01285         CL_WARNPRINTF("Can't determinte the date of %s", szPath);
01286     }
01287 }

static void getExtName ( const char *  szPath,
char *  szExt 
) [static]

Definition at line 1289 of file erMdsFs.c.

01290 {
01291     struct stat statbuf;
01292     char *pChar = NULL;
01293     char *pTmp = NULL;
01294  
01295     if (NULL == szPath || NULL == szExt)
01296     {
01297         CL_ERRORPRINTF("invalid arguments");
01298         return;
01299     }
01300 
01301     strcpy(szExt, "");
01302 
01303     if (strlen(szPath))
01304     {
01305 
01306         if (0 != stat(szPath, &statbuf))
01307         {
01308             CL_WARNPRINTF("entry");
01309             // dummy.bmp doesn't exsits, do something special for it
01310             if (strstr(szPath, "dummy.bmp"))
01311             {
01312                strcpy(szExt, "bmp");
01313             }
01314         }
01315         else
01316         {
01317             if (S_ISREG(statbuf.st_mode))
01318             {
01319                 pChar = strrchr(szPath, (int) '.');
01320                 pTmp = strrchr(szPath, (int) '/');
01321                 // It is only an extension if it is part of the filename
01322                 // Check this by comparing the position of the last '/' 
01323                 // to the position of the last '.'
01324                 // A path will always contain one '/', but we check for a 
01325                 // NULL pointer anyway.
01326                 if (pChar != NULL && (pTmp == NULL || pTmp < pChar))
01327                 {
01328                     strcpy(szExt, ++pChar);
01329                     CL_LOGPRINTF("the extname of %s is %s", szPath, szExt);
01330                 }
01331                 else
01332                 {
01333                     CL_WARNPRINTF("%s does not have a file extension", szPath);
01334                 }
01335             }    
01336             else if(S_ISDIR(statbuf.st_mode))
01337             {
01338                CL_WARNPRINTF("%s is a directory", szPath);
01339             }
01340             else if(S_ISLNK(statbuf.st_mode))
01341             {
01342                CL_WARNPRINTF("%s is a symbollink", szPath);
01343             }
01344             else
01345             {
01346                 CL_WARNPRINTF("entry");
01347             }
01348         }
01349     }
01350     else
01351     {
01352         CL_WARNPRINTF("%s does not have a file extension", szPath);
01353     }
01354 
01355     // report extension always as lower case
01356     for (pChar = szExt ; *pChar ; pChar++)
01357     {
01358         *pChar = tolower(*pChar);
01359     }
01360 }

static void getFakeTitle ( const char *  szPath,
char *  szTitle 
) [static]

Definition at line 883 of file erMdsFs.c.

00884 {
00885     char   *pChar = NULL;
00886 
00887     if (NULL == szPath || NULL == szTitle)
00888     {
00889         CL_ERRORPRINTF("invalid arguments");
00890         return;
00891     }
00892     
00893     strcpy(szTitle, "");
00894 
00895     if (strlen(szPath))
00896     {
00897         // Mobipocket files are different
00898         // We need to try to get the title from the file itself
00899         pChar = strrchr(szPath, (int) '.');
00900         if (pChar != NULL)
00901         {
00902             pChar++;
00903             if (extensionIsMobipocket(pChar))
00904             {
00905                 if (getMobipocketTitle(szPath, szTitle))
00906                 {
00907                     return;
00908                 }
00909             }
00910         }
00911         
00912         // Use filename as title
00913         pChar = strrchr(szPath, (int) '/');
00914         if (pChar != NULL)
00915         {
00916             strcpy(szTitle, ++pChar);
00917         }
00918         else
00919         {
00920             CL_WARNPRINTF("Can not determine title of %s", szPath);
00921         }
00922     }
00923     else
00924     {
00925         CL_WARNPRINTF("Can not determine title of %s", szPath);
00926     }
00927     CL_LOGPRINTF("the title of %s is %s", szPath, szTitle);
00928 }                   

Here is the call graph for this function:

static gboolean getMobipocketTitle ( const char *  szPath,
char *  szTitle 
) [static]

Definition at line 933 of file erMdsFs.c.

00934 {
00935     GIOChannel *io;
00936     guint32 firstRecordIndex = 0;
00937     guint32 titleEncoding = 0;
00938     guint32 titleOffset = 0;
00939     guint32 titleLength = 0;
00940     guint32 check3Value = 0;
00941     int i;
00942     gchar *encoding = NULL;
00943     gchar *p;
00944     GString *tmpTitle;
00945     gunichar uniChar = 0;
00946     GIOStatus st;
00947 
00948     gchar buf[9];
00949     memset(buf, '\0', sizeof(buf));
00950     
00951     CL_LOGPRINTF("entry: [%s]", szPath);
00952     
00953     io = g_io_channel_new_file(szPath, "r", NULL);
00954     if (io != NULL)
00955     {
00956         g_io_channel_set_encoding(io, NULL, NULL); // Binary data
00957 
00958         // First check: make sure this is a Mobipocket document
00959         st = g_io_channel_seek_position(io, MOBIPOCKET_CHECK1_OFFSET, G_SEEK_SET, NULL);
00960         if (st != G_IO_STATUS_NORMAL)
00961         {
00962             CL_ERRORPRINTF("Unable to seek to 0x%x", MOBIPOCKET_CHECK1_OFFSET);
00963             goto return_false;
00964         }
00965         g_io_channel_read_chars(io, buf, 8, NULL, NULL);
00966         buf[8] = '\0';
00967         if (strcmp(buf, "BOOKMOBI") != 0)
00968         {
00969             CL_ERRORPRINTF("Identifier 'BOOKMOBI' not found");
00970             if (strcmp(buf, "TEXtREAd") == 0)
00971             {
00972                 CL_WARNPRINTF("Identifier 'TEXtREAd' found; Assuming PDB title is valid.");
00973                 // Assume UTF-8 encoding and read title from location 0 (PDB mode)
00974                 // This skips all other tests
00975                 firstRecordIndex = 0;
00976                 titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
00977                 titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
00978                 encoding = g_strdup("UTF-8");
00979                 goto read_title;        
00980             }
00981             else
00982             {
00983                 goto return_false;
00984             }
00985         }
00986         memset(buf, '\0', sizeof(buf));
00987 
00988         // Get firstRecordIndex
00989         st = g_io_channel_seek_position(io, MOBIPOCKET_FIRST_RECORD, G_SEEK_SET, NULL);
00990         if (st != G_IO_STATUS_NORMAL)
00991         {
00992             CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex);
00993             goto return_false;
00994         }
00995         g_io_channel_read_chars(io, buf, 4, NULL, NULL);
00996         for (i = 0; i < 4; i++)
00997         {
00998             firstRecordIndex = firstRecordIndex << 8;
00999             firstRecordIndex = firstRecordIndex + buf[i];
01000         }
01001         memset(buf, '\0', sizeof(buf));
01002         
01003         CL_LOGPRINTF("firstRecordIndex = 0x%x", firstRecordIndex);
01004 
01005         // Second check: make sure this is a Mobipocket document
01006         st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_CHECK2_OFFSET, G_SEEK_SET, NULL);
01007         if (st != G_IO_STATUS_NORMAL)
01008         {
01009             CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_CHECK2_OFFSET);
01010             goto return_false;
01011         }
01012         g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01013         buf[4] = '\0';
01014         if (strcmp(buf, "MOBI") != 0)
01015         {
01016             CL_ERRORPRINTF("Identifier 'MOBI' not found");
01017             goto return_false;
01018         }
01019         memset(buf, '\0', sizeof(buf));
01020         
01021         // Get encoding of the title
01022         st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_ENCODING_OFFSET, G_SEEK_SET, NULL);
01023         if (st != G_IO_STATUS_NORMAL)
01024         {
01025             CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_ENCODING_OFFSET);
01026             goto return_false;
01027         }
01028         g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01029         for (i = 0; i < 4; i++)
01030         {
01031             titleEncoding = titleEncoding << 8;
01032             titleEncoding = titleEncoding + buf[i];
01033         }
01034         if (titleEncoding == MOBIPOCKET_ENCODING_UTF8)
01035         {
01036             encoding = g_strdup("UTF-8");
01037         }
01038         else if (titleEncoding == MOBIPOCKET_ENCODING_WIN1252)
01039         {
01040             encoding = g_strdup("WINDOWS-1252");
01041         }
01042         else
01043         {
01044             CL_ERRORPRINTF("Unknown encoding 0x%x", titleEncoding);
01045             goto return_false;
01046         }
01047         memset(buf, '\0', sizeof(buf));
01048 
01049         // Check 3: Make sure this is a Mobipocket document (value must be >= 2)
01050         st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_CHECK3_OFFSET, G_SEEK_SET, NULL);
01051         if (st != G_IO_STATUS_NORMAL)
01052         {
01053             CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_CHECK3_OFFSET);
01054             goto return_false;
01055         }
01056         g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01057         for (i = 0; i < 4; i++)
01058         {
01059             check3Value = check3Value << 8;
01060             check3Value = check3Value + buf[i];
01061         }
01062         memset(buf, '\0', sizeof(buf));
01063 
01064         if (check3Value < 2)
01065         {
01066             // PDB title mode: title is in first 32 bytes of the file
01067             CL_WARNPRINTF("Check 3: value < 2 ; fallback to PDB mode");
01068             firstRecordIndex = 0;
01069             titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
01070             titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
01071         }
01072         else
01073         {
01074             // Normal Mobipocket document: get the title offset
01075         
01076             // Get title offset (big endian int)
01077             st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_TITLE_RECORD_OFFSET, G_SEEK_SET, NULL);
01078             if (st != G_IO_STATUS_NORMAL)
01079             {
01080                 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_TITLE_RECORD_OFFSET);
01081                 goto return_false;
01082             }
01083             g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01084             for (i = 0; i < 4; i++)
01085             {
01086                 titleOffset = titleOffset << 8;
01087                 titleOffset = titleOffset + buf[i];
01088             }
01089             memset(buf, '\0', sizeof(buf));
01090             
01091             // Get title length (big endian int)
01092             st = g_io_channel_seek_position(io, firstRecordIndex + MOBIPOCKET_TITLE_LENGTH_OFFSET, G_SEEK_SET, NULL);
01093             if (st != G_IO_STATUS_NORMAL)
01094             {
01095                 CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + MOBIPOCKET_TITLE_LENGTH_OFFSET);
01096                 goto return_false;
01097             }
01098             g_io_channel_read_chars(io, buf, 4, NULL, NULL);
01099             for (i = 0; i < 4; i++)
01100             {
01101                 titleLength = titleLength << 8;
01102                 titleLength = titleLength + buf[i];
01103             }
01104             memset(buf, '\0', sizeof(buf));
01105             
01106             // Check length and truncate if needed
01107             if (titleLength >= ERMDS_MAX_FILENAME_SIZE)
01108             {
01109                 CL_ERRORPRINTF("titleLength %d >= %d; truncating...", titleLength, ERMDS_MAX_FILENAME_SIZE);
01110                 titleLength = ERMDS_MAX_FILENAME_SIZE - 1;
01111             }
01112             else if (titleLength == 0)
01113             {
01114                 // When the titleLength == 0, we fallback to PDB title mode 
01115                 // and get the title from the first 32 bytes of the file
01116                 CL_WARNPRINTF("titleLength == 0");
01117                 firstRecordIndex = 0;
01118                 titleOffset = MOBIPOCKET_PDB_TITLE_OFFSET;
01119                 titleLength = MOBIPOCKET_PDB_TITLE_LENGTH;
01120             }
01121 
01122         } // if check3Value < 2
01123         
01124 read_title:
01125 
01126         CL_LOGPRINTF("titleLength = %d, titleOffset = 0x%x", titleLength, titleOffset);
01127 
01128         // Get the title at titleOffset, read titleLength bytes
01129         st = g_io_channel_seek_position(io, firstRecordIndex + titleOffset, G_SEEK_SET, NULL);
01130         if (st != G_IO_STATUS_NORMAL)
01131         {
01132             CL_ERRORPRINTF("Unable to seek to 0x%x", firstRecordIndex + titleOffset);
01133             goto return_false;
01134         }
01135         // Set the source encoding for the string to be read
01136         // Strings are automatically converted to unicode when read
01137         st = g_io_channel_set_encoding(io, encoding, NULL);
01138         if (st != G_IO_STATUS_NORMAL)
01139         {
01140             CL_ERRORPRINTF("Unable to change channel encoding to %s", encoding);
01141             goto return_false;
01142         }
01143         
01144         CL_LOGPRINTF("Channel encoding changed to %s", encoding);
01145 
01146         // Read titleLength chars, not bytes (because some chars might be multibyte)
01147         tmpTitle = g_string_sized_new(titleLength);
01148         for (i = 0; i < titleLength; i++)
01149         {
01150             st = g_io_channel_read_unichar(io, &uniChar, NULL);
01151             if (st != G_IO_STATUS_NORMAL)
01152             {
01153                 CL_ERRORPRINTF("Unable to read char from pos %d", i);
01154                 goto return_false;
01155             }
01156             g_string_append_unichar(tmpTitle, uniChar);
01157         }
01158         strcpy(szTitle, tmpTitle->str);
01159         g_string_free(tmpTitle, TRUE); // free the string including character data
01160 
01161         // Replace all '&amp;' references in szTitle with only '&'
01162         while ((p = strstr(szTitle, "&amp;")) != NULL)
01163         {
01164             strcpy(p + 1, p + 5);
01165         }
01166 
01167         CL_LOGPRINTF("Found title [%s]", szTitle);
01168     }
01169     else
01170     {
01171         CL_ERRORPRINTF("Unable to open file [%s]", szPath);
01172         goto return_false;
01173     }
01174     
01175     // All OK, free stuff and close filepointer
01176     if (encoding) g_free(encoding);
01177     g_io_channel_shutdown(io, FALSE, NULL);
01178     g_io_channel_unref(io);
01179     CL_LOGPRINTF("leave");
01180     return TRUE;
01181     
01182 return_false:
01183     if (encoding) g_free(encoding);
01184     if (io)
01185     {
01186         g_io_channel_shutdown(io, FALSE, NULL);
01187         g_io_channel_unref(io);
01188     }
01189 
01190     CL_WARNPRINTF("Not a valid Mobipocket file [%s]", szPath);
01191     return FALSE;
01192 }

static int getSize ( const char *  pathName  )  [static]

Definition at line 1194 of file erMdsFs.c.

01195 {
01196     struct stat statbuf;
01197 
01198     // Determin file size
01199     if (0 != stat(pathName, &statbuf))
01200     {
01201         return ERCL_INVALID_SIZE;
01202     }
01203     
01204     if (S_ISREG(statbuf.st_mode))
01205     {
01206         int size = 0;
01207         size = statbuf.st_blocks * 512;
01208         CL_LOGPRINTF("the title of %s is %d", pathName, size);
01209         return statbuf.st_blocks * 512; // Use blocks here to show size on disk
01210     }    
01211     
01212     if (S_ISDIR(statbuf.st_mode))
01213     {
01214         // visit dir and accumulate
01215         DIR * dir = opendir(pathName);
01216         struct dirent *entry;
01217         int size   = 0, item = 0;
01218         if (NULL == dir) 
01219         {
01220             CL_WARNPRINTF("Open dir returns NULL");
01221             return size;
01222         }
01223         while ((entry = readdir(dir)) != NULL)
01224         {
01225             if (strcmp(".", entry->d_name) && strcmp("..", entry->d_name))
01226             {
01227                 char path[ERMDS_MAX_FILENAME_SIZE] ={0};
01228                 snprintf(path, ERMDS_MAX_FILENAME_SIZE, "%s/%s",
01229                     pathName, entry->d_name);
01230                 item = getSize(path);
01231                 CL_LOGPRINTF("name: %s", path);
01232                 if (ERCL_INVALID_SIZE != item)
01233                 {
01234                     size += item;
01235                 }
01236             }
01237         }       
01238         closedir(dir);
01239         CL_LOGPRINTF("the title of %s is %d", pathName, size);
01240         return size;
01241     }    
01242     return ERCL_INVALID_SIZE;
01243 }

static gboolean is_mobipocket_folder ( const char *  szPath,
const int  len 
) [inline, static]

Definition at line 437 of file erMdsFs.c.

00438 {
00439     const char *cp = &szPath[0];
00440 
00441     if (len > MOBIPOCKET_FOLDER_LENGTH) 
00442     { 
00443         cp += (len - MOBIPOCKET_FOLDER_LENGTH); 
00444     }
00445     else
00446     {
00447         return FALSE;
00448     }
00449      
00450     if (strcmp(cp, MOBIPOCKET_FOLDER) == 0) 
00451     { 
00452         return TRUE;                       
00453     } 
00454     else 
00455     { 
00456         return FALSE; 
00457     } 
00458 }

static void mdsContentPostSort ( GArray *  contentItemArray  )  [static]

Definition at line 402 of file erMdsFs.c.

00403 {
00404     mdsFsItem_t *pFsItem;
00405     int          i, total;
00406 
00407     CL_LOGPRINTF("entry");
00408 
00409     if (contentItemArray)
00410     {
00411         total = contentItemArray->len;
00412         for (i = 0; i < total; i++)
00413         {
00414             pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, i);
00415             if (pFsItem)
00416             {
00417                 if (pFsItem->sortField)
00418                 {
00419                     free(pFsItem->sortField);
00420                     pFsItem->sortField = NULL;
00421                 }
00422             }
00423             else
00424             {
00425                 CL_ERRORPRINTF("Can't get the (%d)th pFsItem.", i);
00426             }
00427         }
00428     }
00429 }

static void mdsContentPreSort ( GArray *  contentItemArray,
mdsSortStruct_t sort 
) [static]

Definition at line 357 of file erMdsFs.c.

00358 {
00359     mdsFsItem_t *pFsItem;
00360     int          i, total;
00361     char         szField[ERMDS_MAX_FILENAME_SIZE];
00362     int          len;
00363    
00364     CL_LOGPRINTF("entry");
00365 
00366     if (contentItemArray && sort)
00367     {
00368         total = contentItemArray->len;
00369         for (i = 0; i < total; i++)
00370         {
00371             pFsItem = &g_array_index(contentItemArray, mdsFsItem_t, i);
00372             if (pFsItem)
00373             {
00374                 // Free the old ones.
00375                 if (pFsItem->sortField)
00376                 {
00377                     free(pFsItem->sortField);
00378                     pFsItem->sortField = NULL;
00379                 }
00380                 // Fetch the string on which to compare.
00381                 mdsFetchField(pFsItem, sort, szField);
00382                 len = strlen(szField) + 1;
00383                 pFsItem->sortField = (char *)malloc(len);
00384                 if (pFsItem->sortField)
00385                 {
00386                     strcpy(pFsItem->sortField, szField);
00387                 }
00388                 else
00389                 {
00390                     CL_ERRORPRINTF("Can't malloc memory for pFsItem->sortField.");
00391                 }
00392             }
00393             else
00394             {
00395                 CL_ERRORPRINTF("Can't get the (%d)th pFsItem.", i);
00396             }
00397         }// for
00398     }
00399 }

Here is the call graph for this function:

static void mdsFetchField ( mdsFsItem_t pFsItem,
mdsSortStruct_t sort,
char *  szField 
) [static]

Definition at line 642 of file erMdsFs.c.

00643 {
00644     if (NULL == pFsItem || NULL == sort || NULL == szField)
00645     {
00646         CL_ERRORPRINTF("invalid arguments");
00647         return;
00648     }
00649 
00650     switch (pFsItem->fit)
00651     {
00652         case mdsFitFile:
00653             mdsFetchFieldOfFile(pFsItem, sort, szField);
00654             break;
00655         case mdsFitFolder:
00656             mdsFetchFieldOfFolder(pFsItem, sort, szField);
00657             break;
00658         case mdsFitSymlink:
00659             mdsFetchFieldOfSymlink(pFsItem, sort, szField);
00660             break;
00661         case mdsFitContainer:
00662             mdsFetchFieldOfContainer(pFsItem, sort, szField);
00663             break;
00664         default:
00665             CL_ERRORPRINTF("fit %d is not defined", pFsItem->fit);
00666             strcpy(szField, "");
00667     }
00668 }

Here is the call graph for this function:

static void mdsFetchFieldOfContainer ( mdsFsItem_t pFsItem,
mdsSortStruct_t sort,
char *  szField 
) [static]

Definition at line 758 of file erMdsFs.c.

00759 {
00760     CL_LOGPRINTF("entry");
00761 
00762    char    szManifestPath[ERMDS_MAX_FILENAME_SIZE];
00763 
00764     if (NULL == pFsItem || NULL == sort || NULL == szField)
00765     {
00766         CL_ERRORPRINTF("invalid arguments");
00767         return;
00768     }
00769     if (mdsFitContainer != pFsItem->fit)
00770     {
00771         CL_ERRORPRINTF("invalid arguments");
00772         return;
00773     }
00774 
00775     // get the field from manifest
00776     if (mdsFieldDate == sort->ft || mdsFieldDescription == sort->ft
00777        || mdsFieldFile == sort->ft || mdsFieldTitle == sort->ft
00778        || mdsFieldSize == sort->ft)
00779     {
00780        // we assume the manifest file exists: no checks
00781        g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, pFsItem->szFilename);
00782        CL_LOGPRINTF("Calling erClXmlFetchField: %s, %d, ...", szManifestPath, (int) sort->ft);
00783        erClXmlFetchField(szManifestPath, sort->ft, szField);
00784     }
00785     else if (mdsFieldExtName == sort->ft)
00786     {
00787         char szStartPage[ERMDS_MAX_FILENAME_SIZE+1];
00788         char szStartPagePath[ERMDS_MAX_FILENAME_SIZE+1];
00789         // we assume the manifest file exists: no checks
00790         g_snprintf(szManifestPath, ERMDS_MAX_FILENAME_SIZE, "%s/" MANIFEST_FILENAME, pFsItem->szFilename);
00791         CL_LOGPRINTF("Calling erClXmlFetchField: %s, %d, ...", szManifestPath, (int) mdsFieldFile);
00792         erClXmlFetchField(szManifestPath, mdsFieldFile, szStartPage);
00793         g_snprintf(szStartPagePath, ERMDS_MAX_FILENAME_SIZE, "%s/%s", pFsItem->szFilename, szStartPage);
00794         getExtName(szStartPagePath, szField);
00795     }
00796     else
00797     {
00798         CL_LOGPRINTF("Field(%d) never be found in manifest.", (int)sort->ft);
00799         strcpy(szField, "");
00800     }
00801     // deal with the scenario we can't get the field value from manifest 
00802     if (0 == strlen(szField))
00803     {
00804         switch (sort->ft)
00805         {
00806             case mdsFieldFsName:
00807                 strcpy(szField, pFsItem->szFilename);
00808                 break;
00809             case mdsFieldDate:
00810                 getDate(pFsItem->szFilename, szField);
00811                 break;
00812             case mdsFieldTitle:
00813                 getFakeTitle(pFsItem->szFilename, szField);
00814                 break;
00815             case mdsFieldSize:
00816                 {
00817                     int size = 0;
00818                     size = getSize(pFsItem->szFilename);
00819                     g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00820                     // write the size of container to manifest.xml 
00821                     erClXmlSetFieldSize(pFsItem->szFilename, size);    
00822                 }
00823                 break;
00824             default:
00825                     CL_ERRORPRINTF("can't get the field value");
00826         }
00827     }
00828     CL_LOGPRINTF("Time of %s: %s", pFsItem->szFilename, szField);
00829 }

Here is the call graph for this function:

static void mdsFetchFieldOfFile ( mdsFsItem_t pFsItem,
mdsSortStruct_t sort,
char *  szField 
) [static]

Definition at line 670 of file erMdsFs.c.

00671 {
00672     CL_LOGPRINTF("entry");
00673 
00674     int     size = 0;
00675     
00676     if (NULL == pFsItem || NULL == sort || NULL == szField)
00677     {
00678         CL_ERRORPRINTF("invalid arguments");
00679         return;
00680     }
00681     if (mdsFitFile != pFsItem->fit)
00682     {
00683         CL_ERRORPRINTF("invalid arguments");
00684         return;
00685     }
00686 
00687     switch (sort->ft)
00688     {
00689         case mdsFieldFsName:
00690             strcpy(szField, pFsItem->szFilename);
00691             break;
00692         case mdsFieldTitle:
00693             getFakeTitle(pFsItem->szFilename, szField);
00694             break;
00695         case mdsFieldDate:
00696             getDate(pFsItem->szFilename, szField);
00697             break;
00698         case mdsFieldSize:
00699             size = getSize(pFsItem->szFilename);
00700             g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00701             break;
00702         case mdsFieldExtName:
00703             getExtName(pFsItem->szFilename, szField);
00704             break;
00705         case mdsFieldAuthor:
00706         case mdsFieldDescription:
00707         case mdsFieldFile:
00708         default:
00709             strcpy(szField, "");
00710     }
00711     CL_LOGPRINTF("%s", szField);
00712 }

Here is the call graph for this function:

static void mdsFetchFieldOfFolder ( mdsFsItem_t pFsItem,
mdsSortStruct_t sort,
char *  szField 
) [static]

Definition at line 714 of file erMdsFs.c.

00715 {
00716     CL_LOGPRINTF("entry");
00717 
00718     if (NULL == pFsItem || NULL == sort || NULL == szField)
00719     {
00720         CL_ERRORPRINTF("invalid arguments");
00721         return;
00722     }
00723     if (pFsItem->fit != mdsFitFolder)
00724     {
00725         CL_ERRORPRINTF("invalid arguments");
00726         return;
00727     }
00728    
00729    switch (sort->ft)
00730    {
00731          case mdsFieldFsName:
00732             strcpy(szField, pFsItem->szFilename);
00733             break;
00734         case mdsFieldTitle:
00735             getFakeTitle(pFsItem->szFilename, szField);
00736             break;
00737         case mdsFieldDate:
00738             getDate(pFsItem->szFilename, szField);
00739             break;
00740         case mdsFieldSize:
00741             {
00742                 // if it's a folder, we treat its size to be zero, otherwise it'll be slow
00743                 // int size = getSize(pFsItem->szFilename);
00744                  int size = 0;
00745                  g_snprintf(szField, ERMDS_MAX_FILENAME_SIZE, "%d", size);
00746             }
00747             break;
00748         case mdsFieldExtName:
00749         case mdsFieldAuthor:
00750         case mdsFieldDescription:
00751         case mdsFieldFile:
00752         default:
00753             strcpy(szField, "");
00754    }
00755    CL_LOGPRINTF("%s", szField);
00756 }

Here is the call graph for this function:

static void mdsFetchFieldOfSymlink ( mdsFsItem_t pFsItem,
mdsSortStruct_t sort,
char *  szField 
) [static]

Definition at line 832 of file erMdsFs.c.

00833 {
00834     CL_LOGPRINTF("entry");
00835 
00836     char*   cp = NULL;
00837     char    szFilename[ERMDS_MAX_FILENAME_SIZE];
00838     char    szRealpath[PATH_MAX];
00839     mdsFsItemType_e fit;
00840     mdsFsItem_t     fsItem;
00841    
00842     if (NULL == pFsItem || NULL == sort || NULL == szField)
00843     {
00844         CL_ERRORPRINTF("invalid arguments");
00845         return;
00846     }
00847     if (mdsFitSymlink != pFsItem->fit)
00848     {
00849         CL_ERRORPRINTF("invalid arguments");
00850         return;
00851     }
00852 
00853     strcpy(szField, ""); 
00854     // Convert symlinks into the real path
00855     // Note: also needed for symlinks in directory path, e.g. /opt/content/books/...
00856     cp = realpath(pFsItem->szFilename, szRealpath);
00857     if (cp != NULL)
00858     {
00859         snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
00860         // Determine the fit and filename for symlinks
00861         erClGetSymlinkInfo(szFilename, &fit);
00862         
00863        if (mdsFitFile == fit || mdsFitFolder == fit || mdsFitContainer == fit)
00864        {
00865           // the realpath is a file or a folder or a container
00866           fsItem.fit = fit;
00867           strcpy(fsItem.szFilename, szFilename);
00868           mdsFetchField(&fsItem, sort, szField);
00869        }
00870        else
00871        {
00872             CL_ERRORPRINTF("entry");
00873        }
00874     }
00875     else
00876     {
00877         CL_ERRORPRINTF("entry");
00878     }
00879 
00880     CL_LOGPRINTF("entry");
00881 }

Here is the call graph for this function:

static gint mdsFieldFsNameComparison ( gconstpointer  a,
gconstpointer  b,
gpointer  user_data 
) [static]

Definition at line 461 of file erMdsFs.c.

00462 {
00463     mdsFsItem_t *pFsItemA = (mdsFsItem_t *) a;
00464     mdsFsItem_t *pFsItemB = (mdsFsItem_t *) b;
00465     mdsSortStruct_t *sort = (mdsSortStruct_t *) user_data;
00466     int     ret;
00467 
00468     // Check to see if one of the files is the Mobipocket special folder
00469     // The Mobipocket special folder always sorts on top
00470 
00471     // If equal priorities, check name
00472     if (pFsItemA->priority == pFsItemB->priority)
00473     {
00474         if (sort->ascending == 1)
00475         {
00476             ret = strcasecmp(pFsItemA->szFilename, pFsItemB->szFilename);
00477         }
00478         else
00479         {
00480             ret = strcasecmp(pFsItemB->szFilename, pFsItemA->szFilename);
00481         }
00482     }
00483     else if (pFsItemA->priority < pFsItemB->priority)
00484     {
00485         ret = 1;
00486     }
00487     else 
00488     {
00489         ret = -1;
00490     }
00491 
00492     return ret;
00493 }

static gint mdsFieldGenericComparison ( gconstpointer  a,
gconstpointer  b,
gpointer  user_data 
) [static]

Definition at line 495 of file erMdsFs.c.

00496 {
00497     mdsFsItem_t     *pFsItemA;
00498     mdsFsItem_t     *pFsItemB;
00499     mdsSortStruct_t *sort;
00500     char            *szFieldA = NULL;
00501     char            *szFieldB = NULL;
00502     int             ret = 0;
00503 
00504     pFsItemA = (mdsFsItem_t *) a;
00505     pFsItemB = (mdsFsItem_t *) b;
00506     sort = (mdsSortStruct_t *) user_data;
00507     
00508     // Check to see if one of the files is the Mobipocket special folder
00509     // The Mobipocket special folder always sorts on top
00510     
00511     // Handle priorities, if priorities are not equal we don't have to do fancy checks
00512     if (pFsItemA->priority != pFsItemB->priority)
00513     {
00514         if (pFsItemA->priority < pFsItemB->priority)
00515         {
00516             return 1;
00517         }
00518         else 
00519         {
00520             return -1;
00521         }
00522     }
00523 
00524     szFieldA = pFsItemA->sortField;
00525     szFieldB = pFsItemB->sortField;
00526 
00527     if (szFieldA && szFieldB)
00528     {
00529         // comparing 
00530         if (mdsFieldDate == sort->ft)
00531         {
00532             ret = datecmp(szFieldA, szFieldB);
00533         }
00534         else if (mdsFieldSize == sort->ft)
00535         {
00536             ret = sizecmp(szFieldA, szFieldB);
00537         }
00538         else
00539         {
00540             ret = strcasecmp(szFieldA, szFieldB);
00541         }
00542     }
00543     else if (szFieldA && NULL == szFieldB)
00544     {
00545         ret = 1;
00546         CL_LOGPRINTF("szFieldA && szFieldB == NULL");
00547     }
00548     else if (NULL == szFieldA && szFieldB)
00549     {
00550         ret = -1;
00551         CL_LOGPRINTF("szFieldA == NULL && szFieldB");
00552     }
00553     else 
00554     {
00555         ret = 0;
00556         CL_LOGPRINTF("szFieldA == szFieldB == NULL");
00557     }
00558 /*
00559     // if equals, we using title to be sorting criteria
00560     if (0 == ret && mdsFieldTitle != sort->ft && mdsFieldFsName != sort->ft) 
00561     {
00562         CL_LOGPRINTF("using sorting type: title");
00563 
00564         mdsSortStruct_t localSort;
00565         char fieldA[ERMDS_MAX_FILENAME_SIZE];
00566         char fieldB[ERMDS_MAX_FILENAME_SIZE];
00567 
00568         localSort.ft = mdsFieldTitle;
00569         localSort.ascending = sort->ascending;
00570 
00571         mdsFetchField(pFsItemA, &localSort, fieldA);
00572         mdsFetchField(pFsItemB, &localSort, fieldB);
00573         ret = strcasecmp(fieldA, fieldB);
00574     }
00575 */    
00576     // if equals, we using filename to be sorting criteria
00577     if (0 == ret && mdsFieldTitle != sort->ft && mdsFieldFsName != sort->ft)
00578     {
00579         CL_LOGPRINTF("using default sorting type: Filename");
00580         ret = strcasecmp(pFsItemA->szFilename, pFsItemB->szFilename);
00581     }
00582     // sort ording
00583     if (sort->ascending == 0) 
00584     {
00585        ret = 0 - ret;
00586     }
00587     CL_LOGPRINTF("ret = %d", ret);
00588     return ret;
00589 }

Here is the call graph for this function:

static int sizecmp ( const char *  sizeA,
const char *  sizeB 
) [static]

Definition at line 617 of file erMdsFs.c.

00618 {
00619     int nSizeA, nSizeB;
00620     int diff = 0;
00621 
00622     CL_LOGPRINTF("entry");
00623    
00624     if (NULL == sizeA || NULL == sizeB)
00625     {
00626         CL_ERRORPRINTF("invalid arguments");
00627         return diff;
00628     }
00629 
00630     nSizeA = atoi(sizeA);
00631     nSizeB = atoi(sizeB);
00632     diff = nSizeA - nSizeB;
00633 
00634     return diff;
00635 }

static void symlinkGetDisplayItem ( mdsFsItem_t pFsItem,
clDisplayItem_t displayItem 
) [static]

Definition at line 1778 of file erMdsFs.c.

01779 {
01780     char*   cp = NULL;
01781     char    szFilename[ERMDS_MAX_FILENAME_SIZE];
01782     char    szRealpath[PATH_MAX];
01783     mdsFsItem_t fsItem;
01784     mdsFsItemType_e fit;
01785 
01786     if (NULL == pFsItem || pFsItem->fit != mdsFitSymlink || NULL == displayItem)
01787     {
01788         CL_ERRORPRINTF("invalid arguments");
01789         return;
01790     }
01791 
01792     // Convert symlinks into the real path
01793     // Note: also needed for symlinks in directory path, e.g. /opt/content/books/...
01794     cp = realpath(pFsItem->szFilename, szRealpath);
01795     if (cp != NULL)
01796     {
01797         // Determine the fit and filename for symlinks
01798         snprintf(szFilename, sizeof(szFilename), "%s", szRealpath);
01799         erClGetSymlinkInfo(szFilename, &fit);
01800         displayItem->fit = fit;
01801 
01802         fsItem.fit = fit;
01803         strcpy(fsItem.szFilename, szFilename);
01804         switch (fit)
01805         {
01806             case mdsFitContainer:
01807                 containerGetDisplayItem(&fsItem, displayItem);
01808                 break;
01809             case mdsFitFile:
01810                 fileGetDisplayItem(&fsItem, displayItem);
01811                 break;
01812             case mdsFitFolder:
01813                 folderGetDisplayItem(&fsItem, displayItem);
01814                 break;
01815             default:
01816                 CL_ERRORPRINTF("entry");
01817                 break;
01818         }
01819     }
01820     else
01821     {
01822         CL_ERRORPRINTF("realpath error on [%s]", pFsItem->szFilename);
01823     }
01824 }

Here is the call graph for this function:


Variable Documentation

Initial value:

 {
                                        { "/mnt/free"   },
                                        { "/mnt/card"   },
                                        { "/mnt/cf"     },
                                        { "/mnt/usb"    },
                                        { "/media/card" },
                                        { "/media/cf"   },
                                        { NULL          }
                                    }

Definition at line 73 of file erMdsFs.c.


Generated on Sun Dec 14 17:13:24 2008 by  doxygen 1.5.6