Added <mkdir> to PXML.xml wherein pndnotifyd will attempt to create some directories...
authorskeezix <skeezix@flotsam-vm.(none)>
Sun, 14 Feb 2010 05:05:47 +0000 (00:05 -0500)
committerskeezix <skeezix@flotsam-vm.(none)>
Sun, 14 Feb 2010 05:05:47 +0000 (00:05 -0500)
Shoudl be used sparingly, bt coudl be handy for guiding user to a needed path, or implying canonicle paths

12 files changed:
apps/pndnotifyd.c
include/pnd_discovery.h
include/pnd_pxml.h
include/pnd_pxml_names.h
include/pnd_utility.h
lib/pnd_discovery.c
lib/pnd_pathiter.h
lib/pnd_pxml.c
lib/pnd_tinyxml.cpp
lib/pnd_utility.c
test/discotest.c
testdata/apps/sampleapp1/PXML.xml

index bf0b47d..f7850df 100644 (file)
@@ -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 ) );
     }
 
       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 );
 
     // next!
     d = pnd_box_get_next ( d );
 
index 707e1e1..e4b11b4 100644 (file)
@@ -66,6 +66,7 @@ typedef struct {
   char *alt_category2;
   char *preview_pic1;
   char *preview_pic2;
   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
 } pnd_disco_t;
 
 void pnd_disco_destroy ( pnd_disco_t *p ); // a function name that simply could not be avoided
index e8853c2..a9733fd 100644 (file)
@@ -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_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 );
 
 // 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 *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;
 
 
 }  pnd_pxml_t;
 
index 15540eb..39f72d2 100644 (file)
@@ -87,6 +87,14 @@ extern "C" {
 #define PND_PXML_ATTRNAME_PACKAGE_NAME "name"
 #define PND_PXML_ATTRNAME_PACKAGE_DATE "released"
 
 #define PND_PXML_ATTRNAME_PACKAGE_NAME "name"
 #define PND_PXML_ATTRNAME_PACKAGE_DATE "released"
 
+/* <mkdir>
+ *   <dir path="..." />
+ * </mkdir>
+ */
+#define PND_PXML_NODENAME_MKDIR "mkdir"
+#define PND_PXML_ENAME_MKDIR "dir"
+#define PND_PXML_ATTRNAME_MKDIRPATH "path"
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 62af5af..f9dce27 100644 (file)
@@ -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 );
 
 //   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
 #ifdef __cplusplus
 } /* "C" */
 #endif
index b29f733..f788065 100644 (file)
@@ -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 -> 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;
 }
 
   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 );
       }
       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" );
 
     } else {
       //printf ( "Invalid PXML; skipping.\n" );
index e91a408..5e13aa8 100644 (file)
@@ -22,6 +22,9 @@
 
 #if 1 // globbing is performed
 
 
 #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;                        \
 #define SEARCHPATH_PRE                            \
   char *end, *colon;                              \
   char *head = searchpath;                        \
                                                   \
   } // while
 
                                                   \
   } // 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
 
 
 #endif // globbing is done
 
 
index 6ad67c3..02d0841 100644 (file)
@@ -497,3 +497,8 @@ char *pnd_pxml_get_startdir ( pnd_pxml_handle h ) {
   pnd_pxml_t *p = (pnd_pxml_t*) h;
   return ( p -> startdir );
 }
   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 );
+}
index 6a7e2e3..b11d450 100644 (file)
@@ -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 );
        }
 
          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 <dir>
+         if ( (pElem = pElem->FirstChildElement(PND_PXML_ENAME_MKDIR)) ) {
+           char *t;
+
+           if ( ( t = pnd_pxml_get_attribute(pElem, PND_PXML_ATTRNAME_MKDIRPATH) ) ) {
+             // first <dir>, 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 <dir>
+
+#if 0
+         if ( app -> mkdir_sp ) {
+           printf ( "mkdir: %s\n", app -> mkdir_sp );
+         }
+#endif
+
+       } // mkdir
+
        return (1);
 }
 
        return (1);
 }
 
index 3733ad0..33b60ef 100644 (file)
@@ -8,6 +8,8 @@
 #include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
 #include <sys/types.h> /* ditto */
 #include <pwd.h> /* ditto */
 #include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
 #include <sys/types.h> /* ditto */
 #include <pwd.h> /* ditto */
+#include <sys/stat.h> /* for fstat */
+#include <dirent.h> /* for opendir */
 
 #include "pnd_pxml.h"
 #include "pnd_container.h"
 
 #include "pnd_pxml.h"
 #include "pnd_container.h"
@@ -223,3 +225,81 @@ pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ) {
 
   return ( pxmlh );
 }
 
   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 );
+}
index 95465bf..cbe1040 100644 (file)
@@ -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 -> 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 ) ) {
 
       if ( do_icon ) {
        if ( pnd_emit_icon ( "./testdata/dotdesktop", d ) ) {
index e761151..88f1962 100644 (file)
@@ -16,6 +16,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="jeff.sample.1" xsi:noN
 
   <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
 
   <author name="EvilDragon" website="http://www.openpandora.org"/><!--Optional email and website, name required-->
 
+  <mkdir>
+    <dir path="common/mydir1"/>
+    <dir path="common/mydir2"/>
+  </mkdir>
+
   <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
   <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->
 
   <version major="1" minor="1" release="1" build="2"/><!--This program's version-->
   <osversion major="1" minor="0" release="0" build="0"/><!--The minimum OS version required-->