From: skeezix Date: Sun, 14 Feb 2010 05:05:47 +0000 (-0500) Subject: Added to PXML.xml wherein pndnotifyd will attempt to create some directories... X-Git-Tag: Release-2010-05/1~117^2~6 X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-libraries.git;a=commitdiff_plain;h=fb01d515a1d360db44093cdb870d37a07b3e2309 Added to PXML.xml wherein pndnotifyd will attempt to create some directories on the SD card hosting the pnd-file, when directed to. Shoudl be used sparingly, bt coudl be handy for guiding user to a needed path, or implying canonicle paths --- diff --git a/apps/pndnotifyd.c b/apps/pndnotifyd.c index bf0b47d..f7850df 100644 --- a/apps/pndnotifyd.c +++ b/apps/pndnotifyd.c @@ -565,6 +565,55 @@ void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char * pnd_log ( pndn_rem, "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) ); } + // does this object request any mkdir's? + if ( d -> mkdir_sp ) { + + // it would appear it does! but we have to carefully validate these suckers + pnd_log ( pndn_rem, " App %s requests mkdir: %s\n", d -> object_path, d -> mkdir_sp ); + + // for each mkdir requested path, do it... + char *searchpath = d -> mkdir_sp; + + SEARCHCHUNK_PRE + { + /* "buffer" now holds each chunk of the searchpath, expanded */ + + // WARN: This whole concept could be flawed; what if they represent '..' in some other obscure way (unicode?) + // and we end up allowing mkdir's all over the place? The risk really is limited -- once the pnd is here, + // if the user _runs it_, it can go nuts, so creating a few dirs isn't all that dangerous... + // HMRF :/ + // Perhaps I should have a config setting for pndnotifyd to suppress this whole mkdir behaviour? + + // if not containing ".." we allow it + if ( strstr ( buffer, ".." ) == NULL ) { + + // determine mountpoint for the file + // - we could deduce this from the path (somewhat risky if we assume leading /media/mmcblk1p1 type notation .. could + // be other distributions entirely + // - better to scan through mount-list and figure it out.. *sucks* + char mountpoint [ PATH_MAX ]; + if ( pnd_determine_mountpoint ( d -> object_path, mountpoint, PATH_MAX - strlen ( buffer ) - 1 ) == 1 ) { + + strcat ( mountpoint, "/" ); + strcat ( mountpoint, buffer ); + + struct stat t; + if ( stat ( mountpoint, &t ) == 0 ) { + pnd_log ( pndn_rem, " Skipping existing mkdir: %s\n", mountpoint ); + } else { + pnd_log ( pndn_rem, " Attempting create of non-existant path: %s\n", mountpoint ); + mkdir ( mountpoint, 0777 ); + } + + } // if figured out the mountpoint + + } // if valid path + + } + SEARCHCHUNK_POST + + } // mkdir request + // next! d = pnd_box_get_next ( d ); diff --git a/include/pnd_discovery.h b/include/pnd_discovery.h index 707e1e1..e4b11b4 100644 --- a/include/pnd_discovery.h +++ b/include/pnd_discovery.h @@ -66,6 +66,7 @@ typedef struct { char *alt_category2; char *preview_pic1; char *preview_pic2; + char *mkdir_sp; } pnd_disco_t; void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could not be avoided diff --git a/include/pnd_pxml.h b/include/pnd_pxml.h index e8853c2..a9733fd 100644 --- a/include/pnd_pxml.h +++ b/include/pnd_pxml.h @@ -83,6 +83,7 @@ char *pnd_pxml_get_associationitem3_parameter ( pnd_pxml_handle h ); char *pnd_pxml_get_clockspeed ( pnd_pxml_handle h ); char *pnd_pxml_get_background ( pnd_pxml_handle h ); char *pnd_pxml_get_startdir ( pnd_pxml_handle h ); +char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ); // for 'set' functions, pass NULL value to delete existing value without setting new one void pnd_pxml_set_app_name ( pnd_pxml_handle h, char *v ); @@ -142,6 +143,7 @@ typedef struct char *exec_no_x11; char *package_name; char *package_release_date; + char *mkdir_sp; // a colon separated list of paths to be mkdir'd (silently fail) when pnd is autodiscovered. path is always relative to the root of the hosting device. } pnd_pxml_t; diff --git a/include/pnd_pxml_names.h b/include/pnd_pxml_names.h index 15540eb..39f72d2 100644 --- a/include/pnd_pxml_names.h +++ b/include/pnd_pxml_names.h @@ -87,6 +87,14 @@ extern "C" { #define PND_PXML_ATTRNAME_PACKAGE_NAME "name" #define PND_PXML_ATTRNAME_PACKAGE_DATE "released" +/* + * + * + */ +#define PND_PXML_NODENAME_MKDIR "mkdir" +#define PND_PXML_ENAME_MKDIR "dir" +#define PND_PXML_ATTRNAME_MKDIRPATH "path" + #ifdef __cplusplus } // extern "C" #endif diff --git a/include/pnd_utility.h b/include/pnd_utility.h index 62af5af..f9dce27 100644 --- a/include/pnd_utility.h +++ b/include/pnd_utility.h @@ -25,6 +25,11 @@ void pnd_exec_no_wait_1 ( char *fullpath, char *arg1 ); // NOTE: Does _NOT_ automatically pick up PXML-overrides; you can call that function if you want pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ); +// determine_mountpoint() will examine a path, and return the mountpoint that this path +// is sitting on; returns 1 on success, meaning the target was populated. +// consider for a similar effect: df /home -> look at "Mounted on" +unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len ); + #ifdef __cplusplus } /* "C" */ #endif diff --git a/lib/pnd_discovery.c b/lib/pnd_discovery.c index b29f733..f788065 100644 --- a/lib/pnd_discovery.c +++ b/lib/pnd_discovery.c @@ -36,6 +36,7 @@ void pnd_disco_destroy ( pnd_disco_t *p ) { if ( p -> alt_category ) { free ( p -> alt_category ); } if ( p -> alt_category1 ) { free ( p -> alt_category1 ); } if ( p -> alt_category2 ) { free ( p -> alt_category2 ); } + if ( p -> mkdir_sp ) { free ( p -> mkdir_sp ); } return; } @@ -213,6 +214,10 @@ static int pnd_disco_callback ( const char *fpath, const struct stat *sb, if ( ( z = pnd_pxml_get_previewpic2 ( pxmlh ) ) ) { p -> preview_pic2 = strdup ( z ); } + // mkdirs + if ( pnd_pxml_get_mkdir ( pxmlh ) ) { + p -> mkdir_sp = strdup ( pnd_pxml_get_mkdir ( pxmlh ) ); + } } else { //printf ( "Invalid PXML; skipping.\n" ); diff --git a/lib/pnd_pathiter.h b/lib/pnd_pathiter.h index e91a408..5e13aa8 100644 --- a/lib/pnd_pathiter.h +++ b/lib/pnd_pathiter.h @@ -22,6 +22,9 @@ #if 1 // globbing is performed +// only iterates actual existing paths; if you want to return +// non-matching paths, see below + #define SEARCHPATH_PRE \ char *end, *colon; \ char *head = searchpath; \ @@ -74,6 +77,47 @@ \ } // while + +// the following will return even non-matching chunks, but is not doing wordexp() expansion on it + +#define SEARCHCHUNK_PRE \ + char *end, *colon; \ + char *head = searchpath; \ + char chunk [ FILENAME_MAX ]; \ + \ + /*fprintf ( stderr, "sp %s\n", searchpath );*/ \ + \ + while ( 1 ) { \ + colon = strchr ( head, ':' ); \ + end = strchr ( head, '\0' ); \ + \ + if ( colon && colon < end ) { \ + memset ( chunk, '\0', FILENAME_MAX ); \ + strncpy ( chunk, head, colon - head ); \ + } else { \ + strncpy ( chunk, head, FILENAME_MAX - 1 ); \ + } \ + \ + /*fprintf ( stderr, "-> %s\n", chunk ); */ \ + \ + char buffer [ FILENAME_MAX ]; \ + \ + strcpy ( buffer, chunk ); \ + /*fprintf ( stderr, "glob %s\n", buffer );*/ \ + { /* user code */ + +#define SEARCHCHUNK_POST \ + } /* user code */ \ + /* next search path */ \ + if ( colon && colon < end ) { \ + head = colon + 1; \ + } else { \ + break; /* done! */ \ + } \ + \ + } // while + + #endif // globbing is done diff --git a/lib/pnd_pxml.c b/lib/pnd_pxml.c index 6ad67c3..02d0841 100644 --- a/lib/pnd_pxml.c +++ b/lib/pnd_pxml.c @@ -497,3 +497,8 @@ char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) { pnd_pxml_t *p = (pnd_pxml_t*) h; return ( p -> startdir ); } + +char *pnd_pxml_get_mkdir ( pnd_pxml_handle h ) { + pnd_pxml_t *p = (pnd_pxml_t*) h; + return ( p -> mkdir_sp ); +} diff --git a/lib/pnd_tinyxml.cpp b/lib/pnd_tinyxml.cpp index 6a7e2e3..b11d450 100644 --- a/lib/pnd_tinyxml.cpp +++ b/lib/pnd_tinyxml.cpp @@ -315,6 +315,43 @@ unsigned char pnd_pxml_parse ( const char *pFilename, char *buffer, unsigned int app -> package_release_date = pnd_pxml_get_attribute ( pElem, PND_PXML_ATTRNAME_PACKAGE_DATE ); } + // mkdir request + if ( (pElem = hRoot.FirstChild(PND_PXML_NODENAME_MKDIR).Element()) ) { + + // seek + if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_MKDIR)) ) { + char *t; + + if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) { + // first , so just replace it wholesale; we use strdup so we can free() easily later, consistently. Mmm, leak seems imminent. + app -> mkdir_sp = strdup ( t ); + } + + while ( ( pElem = pElem -> NextSiblingElement ( PND_PXML_ENAME_MKDIR ) ) ) { + + if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) { + char *foo = (char*) malloc ( strlen ( app -> mkdir_sp ) + strlen ( t ) + 1 /*:*/ + 1 /*\0*/ ); + + if ( foo ) { + sprintf ( foo, "%s:%s", app -> mkdir_sp, t ); + free ( app -> mkdir_sp ); + app -> mkdir_sp = foo; + } // assuming we got ram, lets cat it all together + + } // got another elem? + + } // while + + } // found a + +#if 0 + if ( app -> mkdir_sp ) { + printf ( "mkdir: %s\n", app -> mkdir_sp ); + } +#endif + + } // mkdir + return (1); } diff --git a/lib/pnd_utility.c b/lib/pnd_utility.c index 3733ad0..33b60ef 100644 --- a/lib/pnd_utility.c +++ b/lib/pnd_utility.c @@ -8,6 +8,8 @@ #include /* for expand-tilde below; see commentary for this about-turn */ #include /* ditto */ #include /* ditto */ +#include /* for fstat */ +#include /* for opendir */ #include "pnd_pxml.h" #include "pnd_container.h" @@ -223,3 +225,81 @@ pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ) { return ( pxmlh ); } + +unsigned char pnd_determine_mountpoint ( char *fullpath, char *r_mountpoint, unsigned char mountpoint_len ) { + + // just cheap it, and call df like an idiot. + + // Filesystem 1K-blocks Used Available Use% Mounted on + + char cmd [ PATH_MAX ]; + FILE *p; + char inbuf [ PATH_MAX ]; + + sprintf ( cmd, "/bin/df %s 2>/dev/null", fullpath ); + + if ( ( p = popen ( cmd, "r" ) ) ) { + + // ignore title line; we really shoudl analyze it to figure out which column, but we make assumptions.. + fgets ( inbuf, PATH_MAX, p ); + + if ( ! fgets ( inbuf, PATH_MAX, p ) ) { + pclose ( p ); + return ( 0 ); + } + + pclose ( p ); + + // by now, good + char crap [ PATH_MAX ]; + char mount [ PATH_MAX ]; + if ( sscanf ( inbuf, "%s %s %s %s %s %s", crap, crap, crap, crap, crap, mount ) != 6 ) { + return ( 0 ); + } + + if ( strlen ( mount ) < mountpoint_len ) { + strcpy ( r_mountpoint, mount ); + return ( 1 ); + } + + } // if popen + + return ( 0 ); + +#if 0 + struct stat fooby; + + // can we even stat this file? + if ( stat ( fullpath, &fooby ) == 0 ) { + //dev_t st_dev; /* ID of device containing file */ + //dev_t st_rdev; /* device ID (if special file) */ + + dev_t mount = fooby.st_dev; + + DIR *d = opendir ( "/dev" ); + + if ( d ) { + struct dirent *de; + char path [ FILENAME_MAX ]; + + while ( de = readdir ( d ) ) { + sprintf ( path, "/dev/%s", de -> d_name ); + + if ( stat ( path, &fooby ) == 0 ) { + + // finally, if we find the same major/minor pair in /dev, as we found for the target file, it means we found the right device + if ( fooby.st_rdev == mount ) { + printf ( "Device: %s\n", path ); + } + + } // if + + } // while + + } // opened /dev? + + } // stat +#endif + + return ( 0 ); +} diff --git a/test/discotest.c b/test/discotest.c index 95465bf..cbe1040 100644 --- a/test/discotest.c +++ b/test/discotest.c @@ -157,6 +157,9 @@ int main ( int argc, char *argv[] ) { if ( d -> preview_pic2 ) { printf ( " Preview Pic 2: %s\n", d -> preview_pic2 ); } + if ( d -> mkdir_sp ) { + printf ( " mkdir requests: %s\n", d -> mkdir_sp ); + } if ( do_icon ) { if ( pnd_emit_icon ( "./testdata/dotdesktop", d ) ) { diff --git a/testdata/apps/sampleapp1/PXML.xml b/testdata/apps/sampleapp1/PXML.xml index e761151..88f1962 100644 --- a/testdata/apps/sampleapp1/PXML.xml +++ b/testdata/apps/sampleapp1/PXML.xml @@ -16,6 +16,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.1" xsi:noN + + + + +