Exemple #1
0
const struct file_archive_file_backend* file_archive_get_file_backend(const char *path)
{
   char newpath[PATH_MAX_LENGTH];
   const char *file_ext          = NULL;
   char *last                    = NULL;

   newpath[0] = '\0';

   strlcpy(newpath, path, sizeof(newpath));

   last = (char*)path_get_archive_delim(newpath);

   if (last)
      *last = '\0';

   file_ext = path_get_extension(newpath);

#ifdef HAVE_7ZIP
   if (string_is_equal_noncase(file_ext, "7z"))
      return &sevenzip_backend;
#endif

#ifdef HAVE_ZLIB
   if (     string_is_equal_noncase(file_ext, "zip")
         || string_is_equal_noncase(file_ext, "apk")
      )
      return &zlib_backend;
#endif

   return NULL;
}
Exemple #2
0
/**
 * file_archive_filename_split:
 * @str              : filename to turn into a string list
 *
 * Creates a new string list based on filename @path, delimited by a hash (#).
 *
 * Returns: new string list if successful, otherwise NULL.
 */
static struct string_list *file_archive_filename_split(const char *path)
{
   union string_list_elem_attr attr;
   struct string_list *list = string_list_new();
   const char *delim        = path_get_archive_delim(path);

   memset(&attr, 0, sizeof(attr));

   if (delim)
   {
      /* add archive path to list first */
      if (!string_list_append_n(list, path, delim - path, attr))
         goto error;

      /* now add the path within the archive */
      delim++;

      if (*delim)
      {
         if (!string_list_append(list, delim, attr))
            goto error;
      }
   }
   else
      if (!string_list_append(list, path, attr))
         goto error;

   return list;

error:
   string_list_free(list);
   return NULL;
}
Exemple #3
0
static int file_archive_parse_file_init(file_archive_transfer_t *state,
      const char *file)
{
   char path[PATH_MAX_LENGTH];
   char *last                 = NULL;

   path[0] = '\0';

   strlcpy(path, file, sizeof(path));

   last = (char*)path_get_archive_delim(path);

   if (last)
      *last = '\0';

   state->backend = file_archive_get_file_backend(path);
   if (!state->backend)
      return -1;

   state->handle = file_archive_open(path);
   if (!state->handle)
      return -1;

   state->archive_size = file_archive_size(state->handle);
   state->data         = file_archive_data(state->handle);
   state->footer       = 0;
   state->directory    = 0;

   return state->backend->archive_parse_file_init(state, path);
}
Exemple #4
0
bool core_info_database_supports_content_path(const char *database_path, const char *path)
{
   size_t i;
   char *database           = NULL;
   const char *delim        = NULL;
   const char *archive_path = NULL;

   if (!core_info_curr_list)
      return false;

   database = strdup(path_basename(database_path));

   path_remove_extension(database);

   delim = path_get_archive_delim(path);

   if (delim)
      archive_path = delim - 1;

   /* if the path contains a compressed file and the core supports archives,
    * we don't want to look at this file */
   if (archive_path)
   {
      for (i = 0; i < core_info_curr_list->count; i++)
      {
         const core_info_t *info = &core_info_curr_list->list[i];

         if (!string_list_find_elem(info->databases_list, database))
            continue;

         if (     !string_list_find_elem(info->supported_extensions_list, "zip")
               && !string_list_find_elem(info->supported_extensions_list, "7z"))
            continue;

         free(database);
         return false;
      }
   }

   for (i = 0; i < core_info_curr_list->count; i++)
   {
      const core_info_t *info = &core_info_curr_list->list[i];

      if (!string_list_find_elem(info->supported_extensions_list, path_get_extension(path)))
         continue;

      if (!string_list_find_elem(info->databases_list, database))
         continue;

      free(database);
      return true;
   }

   free(database);
   return false;
}
Exemple #5
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;
}
Exemple #6
0
static int file_archive_extract_cb(const char *name, const char *valid_exts,
      const uint8_t *cdata,
      unsigned cmode, uint32_t csize, uint32_t size,
      uint32_t checksum, struct archive_extract_userdata *userdata)
{
   const char *ext                   = path_get_extension(name);

   /* Extract first file that matches our list. */
   if (ext && string_list_find_elem(userdata->ext, ext))
   {
      char new_path[PATH_MAX_LENGTH];
      char wanted_file[PATH_MAX_LENGTH];
      const char *delim                 = NULL;

      new_path[0] = wanted_file[0]      = '\0';

      if (userdata->extraction_directory)
         fill_pathname_join(new_path, userdata->extraction_directory,
               path_basename(name), sizeof(new_path));
      else
         fill_pathname_resolve_relative(new_path, userdata->archive_path,
               path_basename(name), sizeof(new_path));

      userdata->first_extracted_file_path = strdup(new_path);

      delim = path_get_archive_delim(userdata->archive_path);

      if (delim)
      {
         strlcpy(wanted_file, delim + 1, sizeof(wanted_file));

         if (!string_is_equal_noncase(userdata->extracted_file_path,
                   wanted_file))
           return 1; /* keep searching for the right file */
      }
      else
         strlcpy(wanted_file, userdata->archive_path, sizeof(wanted_file));

      if (file_archive_perform_mode(new_path,
                valid_exts, cdata, cmode, csize, size,
                0, userdata))
         userdata->found_file = true;

      return 0;
   }

   return 1;
}
Exemple #7
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());
}
Exemple #8
0
bool core_info_unsupported_content_path(const char *path)
{
   size_t i;
   const char *archive_path = NULL;
   const char *delim        = path_get_archive_delim(path);

   if (delim)
      archive_path = delim - 1;

   if (!core_info_curr_list)
      return false;

   /* if the path contains a compressed file and the core supports archives,
    * we don't want to look at this file */
   if (archive_path)
   {
      for (i = 0; i < core_info_curr_list->count; i++)
      {
         const core_info_t *info = &core_info_curr_list->list[i];

         if (     !string_list_find_elem(info->supported_extensions_list, "zip")
               && !string_list_find_elem(info->supported_extensions_list, "7z"))
            continue;

         return false;
      }
   }

   for (i = 0; i < core_info_curr_list->count; i++)
   {
      const core_info_t *info = &core_info_curr_list->list[i];

      if (string_list_find_elem(info->supported_extensions_list, path_get_extension(path)))
         return false;
   }

   return true;
}
Exemple #9
0
/**
 * path_contains_compressed_file:
 * @path               : path
 *
 * Checks if path contains a compressed file.
 *
 * Currently we only check for a hash symbol (#) inside the pathname
 * that is preceded by an archive extension. If path is ever expanded
 * to a general URI, we should check for that here.
 *
 * Example:  Somewhere in the path there might be a compressed file
 * E.g.: /path/to/file.7z#mygame.img
 *
 * Returns: true (1) if path contains compressed file, otherwise false (0).
 **/
bool path_contains_compressed_file(const char *path)
{
    return path_get_archive_delim(path) != NULL;
}
Exemple #10
0
/**
 * file_archive_get_file_crc32:
 * @path                         : filename path of archive
 *
 * Returns: CRC32 of the specified file in the archive, otherwise 0.
 * If no path within the archive is specified, the first
 * file found inside is used.
 **/
uint32_t file_archive_get_file_crc32(const char *path)
{
   file_archive_transfer_t state;
   const struct file_archive_file_backend *backend = file_archive_get_file_backend(path);
   struct archive_extract_userdata userdata        = {{0}};
   bool returnerr                                  = false;
   bool contains_compressed                        = false;
   const char *archive_path                        = NULL;

   if (!backend)
      return 0;

   contains_compressed = path_contains_compressed_file(path);

   if (contains_compressed)
   {
      archive_path = path_get_archive_delim(path);

      /* move pointer right after the delimiter to give us the path */
      if (archive_path)
         archive_path += 1;
   }

   state.type          = ARCHIVE_TRANSFER_INIT;
   state.archive_size  = 0;
   state.handle        = NULL;
   state.stream        = NULL;
   state.footer        = NULL;
   state.directory     = NULL;
   state.data          = NULL;
   state.backend       = NULL;

   /* Initialize and open archive first.
      Sets next state type to ITERATE. */
   file_archive_parse_file_iterate(&state,
            &returnerr, path, NULL, NULL,
            &userdata);

   for (;;)
   {
      /* Now find the first file in the archive. */
      if (state.type == ARCHIVE_TRANSFER_ITERATE)
         file_archive_parse_file_iterate(&state,
                  &returnerr, path, NULL, NULL,
                  &userdata);

      /* If no path specified within archive, stop after
       * finding the first file.
       */
      if (!contains_compressed)
         break;

      /* Stop when the right file in the archive is found. */
      if (archive_path)
      {
         if (string_is_equal(userdata.extracted_file_path, archive_path))
            break;
      }
      else
         break;
   }

   file_archive_parse_file_iterate_stop(&state);

   if (userdata.crc)
      return userdata.crc;

   return 0;
}