unsigned char cache_find_writable ( char *originpath, char *r_writepath, unsigned int len ) { static char *searchpaths = NULL; static unsigned int minfree = 0; char searchpath [ PATH_MAX ] = ""; char cmdbuf [ PATH_MAX ]; FILE *f; unsigned int freespace = 0; // figure out the mountpoint for the file, and stick that in at front of searchpath // so that it will get picked first, if possible. char mountpath [ PATH_MAX ]; if ( pnd_determine_mountpoint ( originpath, mountpath, PATH_MAX ) ) { sprintf ( searchpath, "%s:", mountpath ); //pnd_log ( pndn_debug, "Preferred cache target for %s: %s\n", originpath, mountpath ); } // try to find a device, in order of searchpath, with enough space for this cache-out // // populate the searchpath if ( ! searchpaths ) { searchpaths = pnd_conf_get_as_char ( g_conf, "previewpic.cache_searchpath" ); minfree = pnd_conf_get_as_int_d ( g_conf, "previewpic.cache_minfree", 500 ); } if ( ! searchpaths ) { return ( 0 ); // fail! } strncat ( searchpath, searchpaths, PATH_MAX ); SEARCHPATH_PRE { // since I didn't figure out which /sys/block I can pull remaining space from, I'll use df for now :/ sprintf ( cmdbuf, "/bin/df %s", buffer ); f = popen ( cmdbuf, "r" ); if ( f ) { while ( fgets ( cmdbuf, PATH_MAX, f ) ) { // just eat it up // /dev/sdc2 7471392 725260 6366600 11% /media/IMAGE if ( sscanf ( cmdbuf, "%*s %*u %*u %u %*u %*s\n", &freespace ) == 1 ) { strncpy ( r_writepath, buffer, len ); if ( freespace > minfree ) { pclose ( f ); return ( 1 ); } // enough free? } // df } // while pclose ( f ); } } SEARCHPATH_POST return ( 0 ); }
// This very recently was inline code; just slight refactor to functionize it so that it can be // reused in a couple of places. Simple code with simple design quickly became too large for // its simple design; should revisit a lot of these little things.. void process_discoveries ( pnd_box_handle applist, char *emitdesktoppath, char *emiticonpath ) { pnd_disco_t *d = pnd_box_get_head ( applist ); while ( d ) { pnd_log ( pndn_rem, "Found app: %s\n", pnd_box_get_key ( d ) ); // check if icon already exists (from a previous extraction say); if so, we needn't // do it again char existingpath [ FILENAME_MAX ]; sprintf ( existingpath, "%s/%s.png", emiticonpath, d -> unique_id /*, d -> subapp_number */ ); struct stat dirs; if ( stat ( existingpath, &dirs ) == 0 ) { // icon seems to exist, so just crib the location into the .desktop pnd_log ( pndn_rem, " Found icon already existed, so reusing it! %s\n", existingpath ); if ( d -> icon ) { free ( d -> icon ); } d -> icon = strdup ( existingpath ); } else { // icon seems unreadable or does not exist; lets try to create it.. pnd_log ( pndn_debug, " Icon not already present, so trying to write it! %s\n", existingpath ); // handle same-path icon override for davec :) char ovrfile [ PATH_MAX ]; char *fixpxml; sprintf ( ovrfile, "%s/%s", d -> object_path, d -> object_filename ); fixpxml = strcasestr ( ovrfile, PND_PACKAGE_FILEEXT ); if ( fixpxml ) { strcpy ( fixpxml, ".png" ); fixpxml = NULL; struct stat statbuf; if ( stat ( ovrfile, &statbuf ) == 0 ) { d -> icon = strdup ( ovrfile ); fixpxml = ovrfile; // !NULL will be the trigger to skip emittinf desktop from .pnd } // stat } // ovr? // attempt to create icon files; if successful, alter the disco struct to contain new // path, otherwise leave it alone (since it could be a generic icon reference..) if ( fixpxml == NULL ) { // don't have an same-path override icon, so go fetch something from pnd file if ( pnd_emit_icon ( emiticonpath, d ) ) { // success; fix up icon path to new one.. if ( d -> icon ) { free ( d -> icon ); } d -> icon = strdup ( existingpath ); } else { pnd_log ( pndn_debug, " WARN: Couldn't write out icon %s\n", existingpath ); } } // got ovr icon already? } // icon already exists? // create the .desktop file if ( pnd_emit_dotdesktop ( emitdesktoppath, pndrun, d ) ) { // add a watch onto the newly created .desktop? #if 0 char buffer [ FILENAME_MAX ]; sprintf ( buffer, "%s/%s", emitdesktoppath, d -> unique_id ); pnd_notify_watch_path ( nh, buffer, PND_NOTIFY_RECURSE ); #endif } else { pnd_log ( pndn_rem, "ERROR: Error creating .desktop file for app: %s\n", pnd_box_get_key ( d ) ); } // info .desktop if ( g_info_p && info_dotdesktoppath ) { if ( ! pnd_emit_dotinfo ( info_dotdesktoppath, pndrun, d ) ) { pnd_log ( pndn_rem, "ERROR: Error creating info .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 ); } // while applist