/* vim: set sw=2 ts=2 sts=2 et: */ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* * autoar-format-filter.c * Functions related to archive formats and filters * * Copyright (C) 2013 Ting-Wei Lan * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. * */ #include "config.h" #include "autoar-format-filter.h" #include #include #include /** * SECTION:autoar-format-filter * @Short_description: Utilities for handling archive formats and filters * @Title: autoar-format-filter * @Include: gnome-autoar/autoar.h * * autoar-format-filter is a collection of functions providing information * of archive formats and filters. **/ typedef struct _AutoarFormatDescription AutoarFormatDescription; typedef struct _AutoarFilterDescription AutoarFilterDescription; struct _AutoarFormatDescription { AutoarFormat format; int libarchive_format; char *extension; char *keyword; char *mime_type; char *description; AutoarFormatFunc libarchive_read; AutoarFormatFunc libarchive_write; }; struct _AutoarFilterDescription { AutoarFilter filter; int libarchive_filter; char *extension; char *keyword; char *mime_type; char *description; AutoarFilterFunc libarchive_read; AutoarFilterFunc libarchive_write; }; static AutoarFormatDescription autoar_format_description[] = { { AUTOAR_FORMAT_ZIP, ARCHIVE_FORMAT_ZIP, "zip", "zip", "application/zip", "Zip archive", archive_read_support_format_zip, archive_write_set_format_zip }, { AUTOAR_FORMAT_TAR, ARCHIVE_FORMAT_TAR_PAX_RESTRICTED, "tar", "tar", "application/x-tar", "Tar archive (restricted pax)", archive_read_support_format_tar, archive_write_set_format_pax_restricted }, { AUTOAR_FORMAT_CPIO, ARCHIVE_FORMAT_CPIO_POSIX, "cpio", "cpio", "application/x-cpio", "CPIO archive", archive_read_support_format_cpio, archive_write_set_format_cpio }, { AUTOAR_FORMAT_7ZIP, ARCHIVE_FORMAT_7ZIP, "7z", "7z-compressed", "application/x-7z-compressed", "7-zip archive", archive_read_support_format_7zip, archive_write_set_format_7zip }, { AUTOAR_FORMAT_AR_BSD, ARCHIVE_FORMAT_AR_BSD, "a", "ar", "application/x-ar", "AR archive (BSD)", archive_read_support_format_ar, archive_write_set_format_ar_bsd }, { AUTOAR_FORMAT_AR_SVR4, ARCHIVE_FORMAT_AR_GNU, "a", "ar", "application/x-ar", "AR archive (SVR4)", archive_read_support_format_ar, archive_write_set_format_ar_svr4 }, { AUTOAR_FORMAT_CPIO_NEWC, ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, "cpio", "sv4cpio", "application/x-sv4cpio", "SV4 CPIO archive", archive_read_support_format_cpio, archive_write_set_format_cpio_newc }, { AUTOAR_FORMAT_GNUTAR, ARCHIVE_FORMAT_TAR_GNUTAR, "tar", "tar", "application/x-tar", "Tar archive (GNU tar)", archive_read_support_format_gnutar, archive_write_set_format_gnutar }, { AUTOAR_FORMAT_ISO9660, ARCHIVE_FORMAT_ISO9660, "iso", "cd-image", "application/x-cd-image", "Raw CD Image", archive_read_support_format_iso9660, archive_write_set_format_iso9660 }, { AUTOAR_FORMAT_PAX, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE, "tar", "tar", "application/x-tar", "Tar archive (pax)", archive_read_support_format_tar, archive_write_set_format_pax }, { AUTOAR_FORMAT_USTAR, ARCHIVE_FORMAT_TAR_USTAR, "tar", "tar", "application/x-tar", "Tar archive (ustar)", archive_read_support_format_tar, archive_write_set_format_ustar }, { AUTOAR_FORMAT_XAR, ARCHIVE_FORMAT_XAR, "xar", "xar", "application/x-xar", "Xar archive", archive_read_support_format_xar, archive_write_set_format_xar } }; static AutoarFilterDescription autoar_filter_description[] = { { AUTOAR_FILTER_NONE, ARCHIVE_FILTER_NONE, "", "", "", "None", archive_read_support_filter_none, archive_write_add_filter_none }, { AUTOAR_FILTER_COMPRESS, ARCHIVE_FILTER_COMPRESS, "Z", "compress", "application/x-compress", "UNIX-compressed", archive_read_support_filter_compress, archive_write_add_filter_compress }, { AUTOAR_FILTER_GZIP, ARCHIVE_FILTER_GZIP, "gz", "gzip", "application/gzip", "Gzip", archive_read_support_filter_gzip, archive_write_add_filter_gzip }, { AUTOAR_FILTER_BZIP2, ARCHIVE_FILTER_BZIP2, "bz2", "bzip", "application/x-bzip", "Bzip2", archive_read_support_filter_bzip2, archive_write_add_filter_bzip2 }, { AUTOAR_FILTER_XZ, ARCHIVE_FILTER_XZ, "xz", "xz", "application/x-xz", "XZ", archive_read_support_filter_xz, archive_write_add_filter_xz }, { AUTOAR_FILTER_LZMA, ARCHIVE_FILTER_LZMA, "lzma", "lzma", "application/x-lzma", "LZMA", archive_read_support_filter_lzma, archive_write_add_filter_lzma }, { AUTOAR_FILTER_LZIP, ARCHIVE_FILTER_LZIP, "lz", "lzip", "application/x-lzip", "Lzip", archive_read_support_filter_lzip, archive_write_add_filter_lzip }, { AUTOAR_FILTER_LZOP, ARCHIVE_FILTER_LZOP, "lzo", "lzop", "application/x-lzop", "LZO", archive_read_support_filter_lzop, archive_write_add_filter_lzop }, { AUTOAR_FILTER_GRZIP, ARCHIVE_FILTER_GRZIP, "grz", "grzip", "application/x-grzip", "GRZip", archive_read_support_filter_grzip, archive_write_add_filter_grzip }, { AUTOAR_FILTER_LRZIP, ARCHIVE_FILTER_LRZIP, "lrz", "lrzip", "application/x-lrzip", "Long Range ZIP (lrzip)", archive_read_support_filter_lrzip, archive_write_add_filter_lrzip } }; /** * autoar_format_last: * * Gets the maximal allowed values of #AutoarFormat * * Returns: maximal allowed values of #AutoarFormat **/ int autoar_format_last (void) { return AUTOAR_FORMAT_LAST; } /** * autoar_format_is_valid: * @format: an #AutoarFormat * * Checks whether an #AutoarFormat is valid. * * Returns: %TRUE if the value of @format is valid **/ gboolean autoar_format_is_valid (AutoarFormat format) { return (format > 0 && format < AUTOAR_FORMAT_LAST); } /** * autoar_format_get_mime_type: * @format: an #AutoarFormat * * Gets the MIME type of the format from the internal static data. * * Returns: (transfer none): an MIME type **/ const char* autoar_format_get_mime_type (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format) , NULL); return autoar_format_description[format - 1].mime_type; } /** * autoar_format_get_extension: * @format: an #AutoarFormat * * Gets the file name extension of the format from the internal static data. * * Returns: (transfer none): a file name extension **/ const char* autoar_format_get_extension (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); return autoar_format_description[format - 1].extension; } /** * autoar_format_get_description: * @format: an #AutoarFormat * * Gets description of the format from the internal static data. * * Returns: (transfer none): description about the format **/ const char* autoar_format_get_description (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); return autoar_format_description[format - 1].description; } /** * autoar_format_get_format_libarchive: * @format: an #AutoarFormat * * Gets the format code used by libarchive. You can use the return value * as the argument for archive_read_support_format_by_code() and * archive_write_set_format(). However, some format cannot be set using * these two functions because of problems inside libarchive. Use * autoar_format_get_libarchive_read() and * autoar_format_get_libarchive_write() to get the function pointer * is the more reliable way to set format on the archive object. * * Returns: an integer **/ int autoar_format_get_format_libarchive (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format), -1); return autoar_format_description[format - 1].libarchive_format; } /** * autoar_format_get_description_libarchive: * @format: an #AutoarFormat * * Gets description of the format from libarchive. This function creates * and destroys an archive object in order to get the description string. * * Returns: (transfer full): description about the format. Free the returned * string with g_free(). **/ gchar* autoar_format_get_description_libarchive (AutoarFormat format) { struct archive* a; gchar *str; g_return_val_if_fail (autoar_format_is_valid (format), NULL); a = archive_write_new (); archive_write_set_format (a, autoar_format_description[format - 1].libarchive_format); str = g_strdup (archive_format_name (a)); archive_write_free (a); return str; } /** * autoar_format_get_libarchive_read: (skip) * @format: an #AutoarFormat * * Gets the function used to set format on the object returned by * archive_read_new(). * * Returns: function pointer to the setter function provided by libarchive **/ AutoarFormatFunc autoar_format_get_libarchive_read (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); return autoar_format_description[format - 1].libarchive_read; } /** * autoar_format_get_libarchive_write: (skip) * @format: an #AutoarFormat * * Gets the function used to set format on the object returned by * archive_write_new(). * * Returns: function pointer to the setter function provided by libarchive **/ AutoarFormatFunc autoar_format_get_libarchive_write (AutoarFormat format) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); return autoar_format_description[format - 1].libarchive_write; } /** * autoar_filter_last: * * Gets the maximal allowed values of #AutoarFilter * * Returns: maximal allowed values of #AutoarFilter **/ int autoar_filter_last (void) { return AUTOAR_FILTER_LAST; } /** * autoar_filter_is_valid: * @filter: an #AutoarFilter * * Checks whether an #AutoarFilter is valid. * * Returns: %TRUE if the value of @filter is valid **/ gboolean autoar_filter_is_valid (AutoarFilter filter) { return (filter > 0 && filter < AUTOAR_FILTER_LAST); } /** * autoar_filter_get_mime_type: * @filter: an #AutoarFilter * * Gets the MIME type of the filter from the internal static data. * * Returns: (transfer none): an MIME type **/ const char* autoar_filter_get_mime_type (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return autoar_filter_description[filter - 1].mime_type; } /** * autoar_filter_get_extension: * @filter: an #AutoarFilter * * Gets the file name extension of the filter from the internal static data. * * Returns: (transfer none): a file name extension **/ const char* autoar_filter_get_extension (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return autoar_filter_description[filter - 1].extension; } /** * autoar_filter_get_description: * @filter: an #AutoarFilter * * Gets description of the filter from the internal static data. * * Returns: (transfer none): description about the filter **/ const char* autoar_filter_get_description (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return autoar_filter_description[filter - 1].description; } /** * autoar_filter_get_filter_libarchive: * @filter: an #AutoarFilter * * Gets the filter code used by libarchive. You can use the return value * as the argument for archive_write_add_filter(). * * Returns: an integer **/ int autoar_filter_get_filter_libarchive (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), -1); return autoar_filter_description[filter - 1].libarchive_filter; } /** * autoar_filter_get_description_libarchive: * @filter: an #AutoarFilter * * Gets description of the filter from libarchive. This function creates * and destroys an archive object in order to get the description string. * * Returns: (transfer full): description about the filter. Free the returned * string with g_free(). **/ gchar* autoar_filter_get_description_libarchive (AutoarFilter filter) { struct archive *a; gchar *str; g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); a = archive_write_new (); archive_write_add_filter (a, autoar_filter_description[filter - 1].libarchive_filter); str = g_strdup (archive_filter_name (a, 0)); archive_write_free (a); return str; } /** * autoar_filter_get_libarchive_read: (skip) * @filter: an #AutoarFilter * * Gets the function used to add filter on the object returned by * archive_read_new(). * * Returns: function pointer to the setter function provided by libarchive **/ AutoarFilterFunc autoar_filter_get_libarchive_read (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return autoar_filter_description[filter - 1].libarchive_read; } /** * autoar_filter_get_libarchive_write: (skip) * @filter: an #AutoarFilter * * Gets the function used to add filter on the object returned by * archive_write_new(). * * Returns: function pointer to the setter function provided by libarchive **/ AutoarFilterFunc autoar_filter_get_libarchive_write (AutoarFilter filter) { g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return autoar_filter_description[filter - 1].libarchive_write; } /** * autoar_format_filter_get_mime_type: * @format: an #AutoarFormat * @filter: an #AutoarFilter * * Gets the MIME type for an archive @format compressed by * @filter. This function always succeed, but it is not guaranteed * that the returned MIME type exists and can be recognized by applications. * Some combination of format and filter seldom exists in application, * so this function can only generate the string based on some * non-standard rules. * * Returns: (transfer full): an MIME type. Free the returned * string with g_free(). **/ gchar* autoar_format_filter_get_mime_type (AutoarFormat format, AutoarFilter filter) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); switch (filter) { case AUTOAR_FILTER_NONE: return g_strdup (autoar_format_description[format - 1].mime_type); case AUTOAR_FILTER_COMPRESS: return g_strconcat ("application/x-", autoar_format_description[format - 1].keyword, "z", NULL); case AUTOAR_FILTER_GZIP: return g_strconcat ("application/x-compressed-", autoar_format_description[format - 1].keyword, NULL); default: return g_strconcat ("application/x-", autoar_filter_description[filter - 1].keyword, "-compressed-", autoar_format_description[format - 1].keyword, NULL); } } /** * autoar_format_filter_get_extension: * @format: an #AutoarFormat * @filter: an #AutoarFilter * * Gets the file name extension for an archive @format compressed by * @filter. The first character of the returned string is always '.' * * Returns: (transfer full): a file name extension. Free the returned string * with g_free(). **/ gchar* autoar_format_filter_get_extension (AutoarFormat format, AutoarFilter filter) { g_return_val_if_fail (autoar_format_is_valid (format), NULL); g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); return g_strconcat (".", autoar_format_description[format - 1].extension, autoar_filter_description[filter - 1].extension[0] ? "." : "", autoar_filter_description[filter - 1].extension, NULL); } /** * autoar_format_filter_get_description: * @format: an #AutoarFormat * @filter: an #AutoarFilter * * Gets the description for an archive @format compressed by * @filter using #GContentType and autoar_format_filter_get_mime_type(). * * Returns: (transfer full): description about the archive. Free the returned * string with g_free(). **/ gchar* autoar_format_filter_get_description (AutoarFormat format, AutoarFilter filter) { gchar *mime_type; gchar *description; g_return_val_if_fail (autoar_format_is_valid (format), NULL); g_return_val_if_fail (autoar_filter_is_valid (filter), NULL); mime_type = autoar_format_filter_get_mime_type (format, filter); description = g_content_type_get_description (mime_type); g_free (mime_type); return description; }