示例#1
0
/**
 * fill_pathname_parent_dir_name:
 * @out_dir            : output directory
 * @in_dir             : input directory
 * @size               : size of output directory
 *
 * Copies only the parent directory name of @in_dir into @out_dir.
 * The two buffers must not overlap. Removes trailing '/'.
 **/
void fill_pathname_parent_dir_name(char *out_dir,
      const char *in_dir, size_t size)
{
   char *temp = strdup(in_dir);
   char *last = find_last_slash(temp);

   *last = '\0';

   in_dir = find_last_slash(temp) + 1;

   strlcpy(out_dir, in_dir, size);

   free(temp);
}
示例#2
0
/**
 * path_get_archive_delim:
 * @path               : path
 *
 * Find delimiter of an archive file. Only the first '#'
 * after a compression extension is considered.
 *
 * Returns: pointer to the delimiter in the path if it contains
 * a path inside a compressed file, otherwise NULL.
 */
const char *path_get_archive_delim(const char *path)
{
#ifdef HAVE_COMPRESSION
    const char *last = find_last_slash(path);
    const char *delim = NULL;

#ifdef HAVE_ZLIB
    if (last)
    {
        delim = strcasestr(last, ".zip#");

        if (!delim)
            delim = strcasestr(last, ".apk#");
    }

    if (delim)
        return delim + 4;
#endif

#ifdef HAVE_7ZIP
    if (last)
        delim = strcasestr(last, ".7z#");

    if (delim)
        return delim + 3;
#endif

#endif

    return NULL;
}
示例#3
0
/**
 * fill_short_pathname_representation:
 * @out_rep            : output representation
 * @in_path            : input path
 * @size               : size of output representation
 *
 * Generates a short representation of path. It should only
 * be used for displaying the result; the output representation is not
 * binding in any meaningful way (for a normal path, this is the same as basename)
 * In case of more complex URLs, this should cut everything except for
 * the main image file.
 *
 * E.g.: "/path/to/game.img" -> game.img
 *       "/path/to/myarchive.7z#folder/to/game.img" -> game.img
 */
void fill_short_pathname_representation(char* out_rep,
                                        const char *in_path, size_t size)
{
    char path_short[PATH_MAX_LENGTH];
#ifdef HAVE_COMPRESSION
    char *last_slash                  = NULL;
#endif

    path_short[0] = '\0';

    fill_pathname(path_short, path_basename(in_path), "",
                  sizeof(path_short));

#ifdef HAVE_COMPRESSION
    last_slash  = find_last_slash(path_short);
    if (last_slash != NULL)
    {
        /* We handle paths like:
         * /path/to/file.7z#mygame.img
         * short_name: mygame.img:
         *
         * We check whether something is actually
         * after the hash to avoid going over the buffer.
         */
        retro_assert(strlen(last_slash) > 1);
        strlcpy(out_rep, last_slash + 1, size);
    }
    else
#endif
        strlcpy(out_rep, path_short, size);
}
示例#4
0
void fill_pathname_base(char *out, const char *in_path, size_t size)
{
   const char *ptr = find_last_slash(in_path);

   if (ptr)
      ptr++;
   else
      ptr = in_path;

   /* In case of compression, we also have to consider paths like
    *   /path/to/archive.7z#mygame.img
    *   and
    *   /path/to/archive.7z#folder/mygame.img
    *   basename would be mygame.img in both cases
    */

#ifdef HAVE_COMPRESSION
   const char *ptr_bak = ptr;
   ptr = strchr(ptr_bak,'#');
   if (ptr)
      ptr++;
   else
      ptr = ptr_bak;
#endif

   rarch_assert(strlcpy(out, ptr, size) < size);
}
/**
 * fill_short_pathname_representation:
 * @out_rep            : output representation
 * @in_path            : input path
 * @size               : size of output representation
 *
 * Generates a short representation of path. It should only
 * be used for displaying the result; the output representation is not
 * binding in any meaningful way (for a normal path, this is the same as basename)
 * In case of more complex URLs, this should cut everything except for
 * the main image file.
 *
 * E.g.: "/path/to/game.img" -> game.img
 *       "/path/to/myarchive.7z#folder/to/game.img" -> game.img
 */
void fill_short_pathname_representation_wrapper(char* out_rep,
      const char *in_path, size_t size)
{
#ifdef HAVE_COMPRESSION
   char *path_short = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
   char *last_slash = NULL;

   path_short[0]    = '\0';

   fill_pathname(path_short, path_basename(in_path), "",
         PATH_MAX_LENGTH * sizeof(char)
         );

   last_slash  = find_last_slash(path_short);

   if (last_slash != NULL)
   {
      /* We handle paths like:
       * /path/to/file.7z#mygame.img
       * short_name: mygame.img:
       *
       * We check whether something is actually
       * after the hash to avoid going over the buffer.
       */
      retro_assert(strlen(last_slash) > 1);
      strlcpy(out_rep, last_slash + 1, size);
      free(path_short);
      return;
   }

   free(path_short);
#endif

   fill_short_pathname_representation(out_rep, in_path, size);
}
示例#6
0
string path_dirname(const string& path)
{
	size_t index = find_last_slash(path);
	if(index != string::npos) {
#ifndef _WIN32
		if(index == 0 && path.size() > 1) {
			return string(1, DIR_SEP);
		}
#endif
		return path.substr(0, index);
	}
	return "";
}
示例#7
0
/**
 * path_basedir:
 * @path               : path
 *
 * Extracts base directory by mutating path.
 * Keeps trailing '/'.
 **/
void path_basedir(char *path)
{
   char *last = NULL;
   if (strlen(path) < 2)
      return;

   last = find_last_slash(path);

   if (last)
      last[1] = '\0';
   else
      snprintf(path, 3, ".%s", path_default_slash());
}
示例#8
0
/* Assumes path is a directory. Appends a slash
 * if not already there. */
void fill_pathname_slash(char *path, size_t size)
{
   size_t path_len = strlen(path);
   const char *last_slash = find_last_slash(path);

   // Try to preserve slash type.
   if (last_slash && (last_slash != (path + path_len - 1)))
   {
      char join_str[2] = {*last_slash};
      rarch_assert(strlcat(path, join_str, size) < size);
   }
   else if (!last_slash)
      rarch_assert(strlcat(path, path_default_slash(), size) < size);
}
示例#9
0
/**
 * fill_pathname_parent_dir_name:
 * @out_dir            : output directory
 * @in_dir             : input directory
 * @size               : size of output directory
 *
 * Copies only the parent directory name of @in_dir into @out_dir.
 * The two buffers must not overlap. Removes trailing '/'.
 * Returns true on success, false if a slash was not found in the path.
 **/
bool fill_pathname_parent_dir_name(char *out_dir,
      const char *in_dir, size_t size)
{
   char *temp = strdup(in_dir);
   char *last = find_last_slash(temp);
   bool ret = false;

   *last = '\0';

   in_dir = find_last_slash(temp);

   if (in_dir && in_dir + 1)
   {
      strlcpy(out_dir, in_dir + 1, size);
      ret = true;
   }
   else
      ret = false;

   free(temp);

   return ret;
}
示例#10
0
/**
 * fill_pathname_slash:
 * @path               : path
 * @size               : size of path
 *
 * Assumes path is a directory. Appends a slash
 * if not already there.
 **/
void fill_pathname_slash(char *path, size_t size)
{
    size_t path_len = strlen(path);
    const char *last_slash = find_last_slash(path);

    /* Try to preserve slash type. */
    if (last_slash && (last_slash != (path + path_len - 1)))
    {
        char join_str[2];
        strlcpy(join_str, last_slash, sizeof(join_str));
        retro_assert(strlcat(path, join_str, size) < size);
    }
    else if (!last_slash)
        retro_assert(strlcat(path, path_default_slash(), size) < size);
}
示例#11
0
/**
 * path_basename:
 * @path               : path
 *
 * Get basename from @path.
 *
 * Returns: basename from path.
 **/
const char *path_basename(const char *path)
{
   /* We cut either at the first compression-related hash
    * or the last slash; whichever comes last */
   const char *last  = find_last_slash(path);
   const char *delim = path_get_archive_delim(path);

   if (delim)
      return delim + 1;

   if (last)
      return last + 1;

   return path;
}
示例#12
0
const char *path_basename(const char *path)
{
   const char *last = find_last_slash(path);

   /* We cut either at the last hash or the last slash; whichever comes last */
#ifdef HAVE_COMPRESSION
   const char *last_hash = strchr(path,'#');
   if (last_hash > last)
   {
      return last_hash + 1;
   }
#endif

   if (last)
      return last + 1;
   return path;
}
示例#13
0
void path_basedir(char *path)
{
   char *last = NULL;
   if (strlen(path) < 2)
      return;

#ifdef HAVE_COMPRESSION
   /* We want to find the directory with the zipfile in basedir. */
   last = strchr(path,'#');
   if (last)
      *last = '\0';
#endif

   last = find_last_slash(path);

   if (last)
      last[1] = '\0';
   else
      snprintf(path, 3, ".%s", path_default_slash());
}
示例#14
0
/**
 * path_basedir:
 * @path               : path
 *
 * Extracts base directory by mutating path.
 * Keeps trailing '/'.
 **/
void path_basedir_wrapper(char *path)
{
   char *last = NULL;
   if (strlen(path) < 2)
      return;

#ifdef HAVE_COMPRESSION
   /* We want to find the directory with the archive in basedir. */
   last = (char*)path_get_archive_delim(path);
   if (last)
      *last = '\0';
#endif

   last = find_last_slash(path);

   if (last)
      last[1] = '\0';
   else
      snprintf(path, 3, ".%s", path_default_slash());
}
示例#15
0
string path_filename(const string& path)
{
	size_t index = find_last_slash(path);
	if(index != string::npos) {
		/* Corner cases to match boost behavior. */
#ifndef _WIN32
		if(index == 0 && path.size() == 1) {
			return path;
		}
#endif
		if(index == path.size() - 1) {
#ifdef _WIN32
			if(index == 2) {
				return string(1, DIR_SEP);
			}
#endif
			return ".";
		}
		return path.substr(index + 1, path.size() - index - 1);
	}
	return path;
}
示例#16
0
/**
 * path_get_archive_delim:
 * @path               : path
 *
 * Find delimiter of an archive file. Only the first '#'
 * after a compression extension is considered.
 *
 * Returns: pointer to the delimiter in the path if it contains
 * a path inside a compressed file, otherwise NULL.
 */
const char *path_get_archive_delim(const char *path)
{
   const char *last  = find_last_slash(path);
   const char *delim = NULL;

   if (last)
   {
      delim = strcasestr(last, ".zip#");

      if (!delim)
         delim = strcasestr(last, ".apk#");
   }

   if (delim)
      return delim + 4;

   if (last)
      delim = strcasestr(last, ".7z#");

   if (delim)
      return delim + 3;

   return NULL;
}
示例#17
0
/* Updates path for specified thumbnail identifier (right, left).
 * Must be called after:
 * - menu_thumbnail_set_system()
 * - menu_thumbnail_set_content*()
 * ...and before:
 * - menu_thumbnail_get_path()
 * Returns true if generated path is valid */
bool menu_thumbnail_update_path(menu_thumbnail_path_data_t *path_data, enum menu_thumbnail_id thumbnail_id)
{
   settings_t *settings    = config_get_ptr();
   const char *type        = menu_thumbnail_get_type(thumbnail_id);
   const char *system_name = NULL;
   char *thumbnail_path    = NULL;
   char content_dir[PATH_MAX_LENGTH];
   
   if (!path_data)
      return false;
   
   /* Determine which path we are updating... */
   switch (thumbnail_id)
   {
      case MENU_THUMBNAIL_RIGHT:
         thumbnail_path = path_data->right_path;
         break;
      case MENU_THUMBNAIL_LEFT:
         thumbnail_path = path_data->left_path;
         break;
      default:
         return false;
   }
   
   thumbnail_path[0] = '\0';
   
   /* Sundry error checking */
   if (!settings)
      return false;
   
   if (string_is_empty(settings->paths.directory_thumbnails))
      return false;
   
   if (!menu_thumbnail_is_enabled(thumbnail_id))
      return false;
   
   /* Generate new path */
   
   /* > Check path_data for empty strings */
   if (string_is_empty(path_data->content_path) ||
       string_is_empty(path_data->content_img) ||
         (string_is_empty(path_data->system) &&
          string_is_empty(path_data->content_db_name)))
      return false;
   
   /* > Get current system */
   if (string_is_empty(path_data->content_db_name))
   {
      /* If this is a content history or favorites playlist
       * then the current 'path_data->system' string is
       * meaningless. In this case, we fall back to the
       * content directory name */
      if (string_is_equal(path_data->system, "history") ||
          string_is_equal(path_data->system, "favorites"))
      {
         char tmp_buf[PATH_MAX_LENGTH] = {0};
         const char *last_slash = find_last_slash(path_data->content_path);
         
         content_dir[0] = '\0';
         system_name    = content_dir;
         
         if (last_slash)
         {
            size_t path_length = last_slash + 1 - path_data->content_path;
            if ((path_length > 1) && (path_length < PATH_MAX_LENGTH))
            {
               strlcpy(tmp_buf, path_data->content_path, path_length * sizeof(char));
               strlcpy(content_dir, path_basename(tmp_buf), sizeof(content_dir));
            }
         }
         
         if (string_is_empty(system_name))
            return false;
      }
      else
         system_name = path_data->system;
   }
   else
      system_name = path_data->content_db_name;
   
   /* > Special case: thumbnail for imageviewer content
    *   is the image file itself */
   if (string_is_equal(system_name, "images_history") ||
       string_is_equal(path_data->content_core_name, "imageviewer"))
   {
      /* imageviewer content is identical for left and right thumbnails */
      if (path_is_media_type(path_data->content_path) == RARCH_CONTENT_IMAGE)
         strlcpy(thumbnail_path,
            path_data->content_path, PATH_MAX_LENGTH * sizeof(char));
   }
   else
   {
      char tmp_buf[PATH_MAX_LENGTH];
      tmp_buf[0] = '\0';
      
      /* > Normal content: assemble path */
      
      /* >> Base + system name */
      fill_pathname_join(thumbnail_path, settings->paths.directory_thumbnails,
            system_name, PATH_MAX_LENGTH * sizeof(char));
      
      /* >> Add type */
      fill_pathname_join(tmp_buf, thumbnail_path, type, sizeof(tmp_buf));
      
      /* >> Add content image */
      thumbnail_path[0] = '\0';
      fill_pathname_join(thumbnail_path, tmp_buf,
            path_data->content_img, PATH_MAX_LENGTH * sizeof(char));
   }
   
   /* Final error check - is cached path empty? */
   if (string_is_empty(thumbnail_path))
      return false;
   
   return true;
}
示例#18
0
static void task_database_handler(retro_task_t *task)
{
   const char *name                 = NULL;
   database_info_handle_t  *dbinfo  = NULL;
   database_state_handle_t *dbstate = NULL;
   db_handle_t *db                  = NULL;

   if (!task)
      goto task_finished;

   db      = (db_handle_t*)task->state;

   if (!db)
      goto task_finished;

   if (!db->scan_started)
   {
      db->scan_started = true;

      if (!string_is_empty(db->fullpath))
      {
         if (db->is_directory)
            db->handle = database_info_dir_init(db->fullpath, DATABASE_TYPE_ITERATE, task, db->show_hidden_files);
         else
            db->handle = database_info_file_init(db->fullpath, DATABASE_TYPE_ITERATE, task);
      }

      task_free_title(task);

      if (db->handle)
         db->handle->status = DATABASE_STATUS_ITERATE_BEGIN;
   }

   dbinfo  = db->handle;
   dbstate = &db->state;

   if (!dbinfo || task_get_cancelled(task))
      goto task_finished;

   switch (dbinfo->status)
   {
      case DATABASE_STATUS_ITERATE_BEGIN:
         if (dbstate && !dbstate->list)
         {
            if (!string_is_empty(db->content_database_path))
               dbstate->list        = dir_list_new(
                     db->content_database_path,
                     "rdb", false,
                     db->show_hidden_files,
                     false, false);

            /* If the scan path matches a database path exactly then
             * save time by only processing that database. */
            if (dbstate->list && db->is_directory)
            {
               size_t i;
               char *dirname = NULL;

               if (!string_is_empty(db->fullpath))
                  dirname    = find_last_slash(db->fullpath) + 1;

               if (!string_is_empty(dirname))
               {
                  for (i = 0; i < dbstate->list->size; i++)
                  {
                     const char *data = dbstate->list->elems[i].data;
                     char *dbname     = NULL;
                     bool strmatch    = false;
                     char *dbpath     = strdup(data);

                     path_remove_extension(dbpath);

                     dbname         = find_last_slash(dbpath) + 1;
                     strmatch       = strcasecmp(dbname, dirname) == 0;

                     free(dbpath);

                     if (strmatch)
                     {
                        struct string_list *single_list = string_list_new();
                        string_list_append(single_list,
                              data,
                              dbstate->list->elems[i].attr);
                        dir_list_free(dbstate->list);
                        dbstate->list = single_list;
                        break;
                     }
                  }
               }
            }
         }
         dbinfo->status = DATABASE_STATUS_ITERATE_START;
         break;
      case DATABASE_STATUS_ITERATE_START:
         name = database_info_get_current_element_name(dbinfo);
         task_database_cleanup_state(dbstate);
         dbstate->list_index  = 0;
         dbstate->entry_index = 0;
         task_database_iterate_start(dbinfo, name);
         break;
      case DATABASE_STATUS_ITERATE:
         if (task_database_iterate(db, dbstate, dbinfo) == 0)
         {
            dbinfo->status = DATABASE_STATUS_ITERATE_NEXT;
            dbinfo->type   = DATABASE_TYPE_ITERATE;
         }
         break;
      case DATABASE_STATUS_ITERATE_NEXT:
         if (task_database_iterate_next(dbinfo) == 0)
         {
            dbinfo->status = DATABASE_STATUS_ITERATE_START;
            dbinfo->type   = DATABASE_TYPE_ITERATE;
         }
         else
         {
            const char *msg = NULL;
            if (db->is_directory)
               msg = msg_hash_to_str(MSG_SCANNING_OF_DIRECTORY_FINISHED);
            else
               msg = msg_hash_to_str(MSG_SCANNING_OF_FILE_FINISHED);
#ifdef RARCH_INTERNAL
            runloop_msg_queue_push(msg, 0, 180, true);
#else
            fprintf(stderr, "msg: %s\n", msg);
#endif
            ui_companion_driver_notify_refresh();
            goto task_finished;
         }
         break;
      default:
      case DATABASE_STATUS_FREE:
      case DATABASE_STATUS_NONE:
         goto task_finished;
   }

   return;
task_finished:
   if (task)
      task_set_finished(task, true);

   if (dbstate)
   {
      if (dbstate->list)
         dir_list_free(dbstate->list);
   }

   if (db)
   {
      if (!string_is_empty(db->playlist_directory))
         free(db->playlist_directory);
      if (!string_is_empty(db->content_database_path))
         free(db->content_database_path);
      if (!string_is_empty(db->fullpath))
         free(db->fullpath);
      if (db->state.buf)
         free(db->state.buf);

      if (db->handle)
         database_info_free(db->handle);
      free(db);
   }

   if (dbinfo)
      free(dbinfo);
}
示例#19
0
/* Initialise runtime log, loading current parameters
 * if log file exists. Returned object must be free()'d.
 * Returns NULL if content_path and/or core_path are invalid */
runtime_log_t *runtime_log_init(const char *content_path, const char *core_path, bool log_per_core)
{
   settings_t *settings = config_get_ptr();
   core_info_list_t *core_info = NULL;
   runtime_log_t *runtime_log = NULL;
   const char *core_path_basename = path_basename(core_path);
   
   char content_name[PATH_MAX_LENGTH];
   char core_name[PATH_MAX_LENGTH];
   char log_file_dir[PATH_MAX_LENGTH];
   char log_file_path[PATH_MAX_LENGTH];
   char tmp_buf[PATH_MAX_LENGTH];
   
   unsigned i;
   
   content_name[0] = '\0';
   core_name[0] = '\0';
   log_file_dir[0] = '\0';
   log_file_path[0] = '\0';
   tmp_buf[0] = '\0';
   
   /* Error checking */
   if (!settings)
      return NULL;
   
   if (string_is_empty(settings->paths.directory_playlist))
   {
      RARCH_ERR("Playlist directory is undefined - cannot save runtime logs.\n");
      return NULL;
   }
   
   if (string_is_empty(content_path) || string_is_empty(core_path_basename))
      return NULL;
   
   if (string_is_equal(core_path, "builtin") || string_is_equal(core_path, file_path_str(FILE_PATH_DETECT)))
      return NULL;
   
   /* Get core name
    * Note: An annoyance - this is required even when
    * we are performing aggregate (not per core) logging,
    * since content name is sometimes dependent upon core
    * (e.g. see TyrQuake below) */
   core_info_get_list(&core_info);
   
   if (!core_info)
      return NULL;
   
   for (i = 0; i < core_info->count; i++)
   {
      if (string_is_equal(path_basename(core_info->list[i].path), core_path_basename))
      {
         strlcpy(core_name, core_info->list[i].core_name, sizeof(core_name));
         break;
      }
   }
   
   if (string_is_empty(core_name))
      return NULL;
   
   /* Get runtime log directory */
   fill_pathname_join(
         tmp_buf,
         settings->paths.directory_playlist,
         "logs",
         sizeof(tmp_buf));
   
   if (log_per_core)
   {
      fill_pathname_join(
            log_file_dir,
            tmp_buf,
            core_name,
            sizeof(log_file_dir));
   }
   else
   {
      strlcpy(log_file_dir, tmp_buf, sizeof(log_file_dir));
   }
   
   if (string_is_empty(log_file_dir))
      return NULL;
   
   /* Create directory, if required */
   if (!path_is_directory(log_file_dir))
   {
      path_mkdir(log_file_dir);
      
      if(!path_is_directory(log_file_dir))
      {
         RARCH_ERR("Failed to create directory for runtime log: %s.\n", log_file_dir);
         return NULL;
      }
   }
   
   /* Get content name
    * Note: TyrQuake requires a specific hack, since all
    * content has the same name... */
   if (string_is_equal(core_name, "TyrQuake"))
   {
      const char *last_slash = find_last_slash(content_path);
      if (last_slash)
      {
         size_t path_length = last_slash + 1 - content_path;
         if (path_length < PATH_MAX_LENGTH)
         {
            memset(tmp_buf, 0, sizeof(tmp_buf));
            strlcpy(tmp_buf, content_path, path_length * sizeof(char));
            strlcpy(content_name, path_basename(tmp_buf), sizeof(content_name));
         }
      }
   }
   else
   {
      /* path_remove_extension() requires a char * (not const)
       * so have to use a temporary buffer... */
      tmp_buf[0] = '\0';
      strlcpy(tmp_buf, path_basename(content_path), sizeof(tmp_buf));
      strlcpy(content_name, path_remove_extension(tmp_buf), sizeof(content_name));
   }
   
   if (string_is_empty(content_name))
      return NULL;
   
   /* Build final log file path */
   fill_pathname_join(log_file_path, log_file_dir, content_name, sizeof(log_file_path));
   strlcat(log_file_path, file_path_str(FILE_PATH_RUNTIME_EXTENSION), sizeof(log_file_path));
   
   if (string_is_empty(log_file_path))
      return NULL;
   
   /* Phew... If we get this far then all is well.
    * > Create 'runtime_log' object */
   runtime_log = (runtime_log_t*)calloc(1, sizeof(*runtime_log));
   if (!runtime_log)
      return NULL;
   
   /* > Populate default values */
   runtime_log->runtime.hours = 0;
   runtime_log->runtime.minutes = 0;
   runtime_log->runtime.seconds = 0;
   
   runtime_log->last_played.year = 0;
   runtime_log->last_played.month = 0;
   runtime_log->last_played.day = 0;
   runtime_log->last_played.hour = 0;
   runtime_log->last_played.minute = 0;
   runtime_log->last_played.second = 0;
   
   strlcpy(runtime_log->path, log_file_path, sizeof(runtime_log->path));
   
   /* Load existing log file, if it exists */
   runtime_log_read_file(runtime_log);
   
   return runtime_log;
}