X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=blobdiff_plain;f=lib%2Fpnd_discovery.c;h=e1fc0ef09c43cec7453c32582224ec7f2ae0b6c9;hp=d32a591e0bfb8cd8790b7907174f4ca00c6dbf73;hb=54ea6b85bca341e53836985e5ab8404341393361;hpb=dcb607f8312d117aa5827925a9602ff2363eabf1 diff --git a/lib/pnd_discovery.c b/lib/pnd_discovery.c index d32a591..e1fc0ef 100644 --- a/lib/pnd_discovery.c +++ b/lib/pnd_discovery.c @@ -2,12 +2,16 @@ #include /* for FILE etc */ #include /* for malloc */ #include /* for unlink */ +#include /* for PATH_MAX */ +#include +#include #define __USE_GNU /* for strcasestr */ #include /* for making ftw.h happy */ #define _XOPEN_SOURCE 500 #define __USE_XOPEN_EXTENDED +#define _GNU_SOURCE #include /* for nftw, tree walker */ #include "pnd_container.h" @@ -17,6 +21,7 @@ #include "pnd_apps.h" #include "pnd_pndfiles.h" #include "pnd_logger.h" +#include "pnd_conf.h" // need these 'globals' due to the way nftw and ftw work :/ static pnd_box_handle disco_box; @@ -26,6 +31,7 @@ void pnd_disco_destroy ( pnd_disco_t *p ) { if ( p -> title_en ) { free ( p -> title_en ); } if ( p -> unique_id ) { free ( p -> unique_id ); } + if ( p -> appdata_dirname ) { free ( p -> appdata_dirname ); } if ( p -> icon ) { free ( p -> icon ); } if ( p -> exec ) { free ( p -> exec ); } if ( p -> execargs ) { free ( p -> execargs ); } @@ -39,6 +45,9 @@ void pnd_disco_destroy ( pnd_disco_t *p ) { if ( p -> alt_category1 ) { free ( p -> alt_category1 ); } if ( p -> alt_category2 ) { free ( p -> alt_category2 ); } if ( p -> mkdir_sp ) { free ( p -> mkdir_sp ); } + if ( p -> info_name ) { free ( p -> info_name ); } + if ( p -> info_type ) { free ( p -> info_type ); } + if ( p -> info_filename ) { free ( p -> info_filename ); } return; } @@ -62,7 +71,10 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, if ( logit ) { pnd_log ( PND_LOG_DEFAULT, " .. is dir, skipping\n" ); } - return ( 0 ); // skip directories and other non-regular files + if ( ftwbuf -> level >= pathiter_depthlimit ) { + return ( FTW_SKIP_SUBTREE ); + } + return ( FTW_CONTINUE ); // skip directories and other non-regular files } // PND/PNZ file and others may be valid as well .. but lets leave that for now @@ -78,7 +90,7 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, if ( logit ) { pnd_log ( PND_LOG_DEFAULT, " .. bad filename, skipping\n" ); } - return ( 0 ); + return ( FTW_CONTINUE ); } // potentially a valid application @@ -106,13 +118,13 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, // try to locate the PXML portion if ( ! pnd_pnd_seek_pxml ( f ) ) { fclose ( f ); - return ( 0 ); // pnd or not, but not to spec. Pwn'd the pnd? + return ( FTW_CONTINUE ); // pnd or not, but not to spec. Pwn'd the pnd? } // accrue it into a buffer if ( ! pnd_pnd_accrue_pxml ( f, pxmlbuf, 32 * 1024 ) ) { fclose ( f ); - return ( 0 ); + return ( FTW_CONTINUE ); } //printf ( "buffer is %s\n", pxmlbuf ); @@ -121,18 +133,21 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, #if 1 // icon // for convenience, lets skip along past trailing newlines/CR's in hopes of finding icon data? { - unsigned int pos = ftell ( f ); char pngbuffer [ 16 ]; // \211 P N G \r \n \032 \n pngbuffer [ 0 ] = 137; pngbuffer [ 1 ] = 80; pngbuffer [ 2 ] = 78; pngbuffer [ 3 ] = 71; pngbuffer [ 4 ] = 13; pngbuffer [ 5 ] = 10; pngbuffer [ 6 ] = 26; pngbuffer [ 7 ] = 10; - unsigned char padtests = 10; + unsigned char padtests = 20; unsigned int padstart = ftell ( f ); + + // seek back 10 (should be back into the /PXML> part) to catch any appending-icon-no-line-endings funny business + fseek ( f, -10, SEEK_CUR ); + while ( padtests ) { if ( fread ( pngbuffer + 8, 8, 1, f ) == 1 ) { if ( memcmp ( pngbuffer, pngbuffer + 8, 8 ) == 0 ) { - pxml_close_pos = pos; + pxml_close_pos = ftell ( f ) - 8; break; } // if fseek ( f, -7, SEEK_CUR ); // seek back 7 (so we're 1 further than we started, since PNG header is 8b) @@ -159,9 +174,13 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, // pxmlh is useful? if ( ! pxmlapps ) { - return ( 0 ); // continue tree walk + return ( FTW_CONTINUE ); // continue tree walk } + // for ovr-file + char ovrfile [ PATH_MAX ]; + pnd_box_handle ovrh = 0; // 0 didn't try, -1 tried and failed, >0 tried and got + // iterate across apps in the PXML pxmlappiter = pxmlapps; while ( 1 ) { @@ -172,16 +191,13 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, break; // all done } - // look for any overrides, if requested - pnd_pxml_merge_override ( pxmlh, disco_overrides ); - // check for validity and add to resultset if it looks executable if ( pnd_is_pxml_valid_app ( pxmlh ) ) { pnd_disco_t *p; char *fixpxml; char *z; - pnd_log ( PND_LOG_DEFAULT, "Setting up discovered app %u\n", ((pnd_pxml_t*) pxmlh) -> subapp_number ); + //pnd_log ( PND_LOG_DEFAULT, "Setting up discovered app %u\n", ((pnd_pxml_t*) pxmlh) -> subapp_number ); p = pnd_box_allocinsert ( disco_box, (char*) fpath, sizeof(pnd_disco_t) ); @@ -229,6 +245,9 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, if ( pnd_pxml_get_unique_id ( pxmlh ) ) { p -> unique_id = strdup ( pnd_pxml_get_unique_id ( pxmlh ) ); } + if ( pnd_pxml_get_appdata_dirname ( pxmlh ) ) { + p -> appdata_dirname = strdup ( pnd_pxml_get_appdata_dirname ( pxmlh ) ); + } if ( pnd_pxml_get_clockspeed ( pxmlh ) ) { p -> clockspeed = strdup ( pnd_pxml_get_clockspeed ( pxmlh ) ); } @@ -265,6 +284,100 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, if ( pnd_pxml_get_mkdir ( pxmlh ) ) { p -> mkdir_sp = strdup ( pnd_pxml_get_mkdir ( pxmlh ) ); } + // info + if ( pnd_pxml_get_info_src ( pxmlh ) ) { + p -> info_filename = strdup ( pnd_pxml_get_info_src ( pxmlh ) ); + } + if ( pnd_pxml_get_info_name ( pxmlh ) ) { + p -> info_name = strdup ( pnd_pxml_get_info_name ( pxmlh ) ); + } + if ( pnd_pxml_get_info_type ( pxmlh ) ) { + p -> info_type = strdup ( pnd_pxml_get_info_type ( pxmlh ) ); + } + + // look for any PXML overrides, if requested + if ( disco_overrides ) { + pnd_pxml_merge_override ( pxmlh, disco_overrides ); + } + + // handle ovr overrides + // try to load a same-path-as-pnd override file + if ( ovrh == 0 ) { + sprintf ( ovrfile, "%s/%s", p -> object_path, p -> object_filename ); + fixpxml = strcasestr ( ovrfile, PND_PACKAGE_FILEEXT ); + if ( fixpxml ) { + strcpy ( fixpxml, PXML_SAMEPATH_OVERRIDE_FILEEXT ); + struct stat statbuf; + if ( stat ( ovrfile, &statbuf ) == 0 ) { + ovrh = pnd_conf_fetch_by_path ( ovrfile ); + + if ( ! ovrh ) { + // couldn't pull conf out of file, so don't try again + ovrh = (void*)(-1); + } + + } else { + ovrh = (void*)(-1); // not found, don't try again + } // stat + } // can find .pnd + } // tried ovr yet? + + // is ovr file open? + if ( ovrh != 0 && ovrh != (void*)(-1) ) { + // pull in appropriate values + char key [ 100 ]; + char *v; + + // set the flag regardless, so its for all subapps + p -> object_flags |= PND_DISCO_FLAG_OVR; + + // title + snprintf ( key, 100, "Application-%u.title", p -> subapp_number ); + if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) { + if ( p -> title_en ) { + free ( p -> title_en ); + } + p -> title_en = strdup ( v ); + } + + // clockspeed + snprintf ( key, 100, "Application-%u.clockspeed", p -> subapp_number ); + if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) { + if ( p -> clockspeed ) { + free ( p -> clockspeed ); + } + p -> clockspeed = strdup ( v ); + } + + // appdata dirname + snprintf ( key, 100, "Application-%u.appdata", p -> subapp_number ); + if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) { + if ( p -> appdata_dirname ) { + free ( p -> appdata_dirname ); + } + p -> appdata_dirname = strdup ( v ); + } + + // categories + snprintf ( key, 100, "Application-%u.maincategory", p -> subapp_number ); + if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) { + if ( p -> main_category ) { + free ( p -> main_category ); + } + p -> main_category = strdup ( v ); + } + snprintf ( key, 100, "Application-%u.maincategorysub1", p -> subapp_number ); + if ( ( v = pnd_conf_get_as_char ( ovrh, key ) ) ) { + if ( p -> main_category1 ) { + free ( p -> main_category1 ); + p -> main_category1 = NULL; + } + if ( strcasecmp ( v, "NoSubcategory" ) != 0 ) { + p -> main_category1 = strdup ( v ); + } + } + + } // got ovr conf loaded? } else { //printf ( "Invalid PXML; skipping.\n" ); @@ -275,10 +388,15 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, } // while pxmlh is good + // free up ovr + if ( ovrh != 0 && ovrh != (void*)(-1) ) { + pnd_box_delete ( ovrh ); + } + // free up the applist free ( pxmlapps ); - return ( 0 ); // continue the tree walk + return ( FTW_CONTINUE ); // continue the tree walk } pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) { @@ -299,7 +417,7 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) { nftw ( buffer, // path to descend pnd_disco_callback, // callback to do processing 10, // no more than X open fd's at once - FTW_PHYS ); // do not follow symlinks + FTW_PHYS | FTW_ACTIONRETVAL ); // do not follow symlinks } SEARCHPATH_POST @@ -312,3 +430,34 @@ pnd_box_handle pnd_disco_search ( char *searchpath, char *overridespath ) { return ( disco_box ); } + +pnd_box_handle pnd_disco_file ( char *path, char *filename ) { + struct stat statbuf; + + // set up container + disco_overrides = NULL; + disco_box = pnd_box_new ( "discovery" ); + + // path + char fullpath [ PATH_MAX ]; + sprintf ( fullpath, "%s/%s", path, filename ); + + // fake it + if ( stat ( fullpath, &statbuf ) < 0 ) { + return ( 0 ); + } + + struct FTW ftw; + ftw.base = strlen ( path ); + ftw.level = 0; + + pnd_disco_callback ( fullpath, &statbuf, FTW_F, &ftw ); + + // return whatever we found, or NULL if nada + if ( ! pnd_box_get_head ( disco_box ) ) { + pnd_box_delete ( disco_box ); + disco_box = NULL; + } + + return ( disco_box ); +}