mirror of
https://git.tukaani.org/xz.git
synced 2024-04-04 12:36:23 +02:00
145 lines
3.9 KiB
C
145 lines
3.9 KiB
C
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
/// \file suffix.c
|
|
/// \brief Checks filename suffix and creates the destination filename
|
|
//
|
|
// Copyright (C) 2007 Lasse Collin
|
|
//
|
|
// 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.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "private.h"
|
|
|
|
|
|
static const struct {
|
|
const char *compressed;
|
|
const char *uncompressed;
|
|
} suffixes[] = {
|
|
{ ".lzma", "" },
|
|
{ ".tlz", ".tar" },
|
|
{ ".ylz", ".yar" },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
/// \brief Checks if src_name has given compressed_suffix
|
|
///
|
|
/// \param suffix Filename suffix to look for
|
|
/// \param src_name Input filename
|
|
/// \param src_len strlen(src_name)
|
|
///
|
|
/// \return If src_name has the suffix, src_len - strlen(suffix) is
|
|
/// returned. It's always a positive integer. Otherwise zero
|
|
/// is returned.
|
|
static size_t
|
|
test_suffix(const char *suffix, const char *src_name, size_t src_len)
|
|
{
|
|
const size_t suffix_len = strlen(suffix);
|
|
|
|
// The filename must have at least one character in addition to
|
|
// the suffix. src_name may contain path to the filename, so we
|
|
// need to check for directory separator too.
|
|
if (src_len <= suffix_len || src_name[src_len - suffix_len - 1] == '/')
|
|
return 0;
|
|
|
|
if (strcmp(suffix, src_name + src_len - suffix_len) == 0)
|
|
return src_len - suffix_len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/// \brief Removes the filename suffix of the compressed file
|
|
///
|
|
/// \return Name of the uncompressed file, or NULL if file has unknown
|
|
/// suffix.
|
|
static char *
|
|
uncompressed_name(const char *src_name)
|
|
{
|
|
const char *new_suffix = "";
|
|
const size_t src_len = strlen(src_name);
|
|
size_t new_len = 0;
|
|
|
|
for (size_t i = 0; suffixes[i].compressed != NULL; ++i) {
|
|
new_len = test_suffix(suffixes[i].compressed,
|
|
src_name, src_len);
|
|
if (new_len != 0) {
|
|
new_suffix = suffixes[i].uncompressed;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (new_len == 0 && opt_suffix != NULL)
|
|
new_len = test_suffix(opt_suffix, src_name, src_len);
|
|
|
|
if (new_len == 0) {
|
|
errmsg(V_WARNING, _("%s: Filename has an unknown suffix, "
|
|
"skipping"), src_name);
|
|
return NULL;
|
|
}
|
|
|
|
const size_t new_suffix_len = strlen(new_suffix);
|
|
char *dest_name = malloc(new_len + new_suffix_len + 1);
|
|
if (dest_name == NULL) {
|
|
out_of_memory();
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(dest_name, src_name, new_len);
|
|
memcpy(dest_name + new_len, new_suffix, new_suffix_len);
|
|
dest_name[new_len + new_suffix_len] = '\0';
|
|
|
|
return dest_name;
|
|
}
|
|
|
|
|
|
/// \brief Appends suffix to src_name
|
|
static char *
|
|
compressed_name(const char *src_name)
|
|
{
|
|
const size_t src_len = strlen(src_name);
|
|
|
|
for (size_t i = 0; suffixes[i].compressed != NULL; ++i) {
|
|
if (test_suffix(suffixes[i].compressed, src_name, src_len)
|
|
!= 0) {
|
|
errmsg(V_WARNING, _("%s: File already has `%s' "
|
|
"suffix, skipping"), src_name,
|
|
suffixes[i].compressed);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
const char *suffix = opt_suffix != NULL
|
|
? opt_suffix : suffixes[0].compressed;
|
|
const size_t suffix_len = strlen(suffix);
|
|
|
|
char *dest_name = malloc(src_len + suffix_len + 1);
|
|
if (dest_name == NULL) {
|
|
out_of_memory();
|
|
return NULL;
|
|
}
|
|
|
|
memcpy(dest_name, src_name, src_len);
|
|
memcpy(dest_name + src_len, suffix, suffix_len);
|
|
dest_name[src_len + suffix_len] = '\0';
|
|
|
|
return dest_name;
|
|
}
|
|
|
|
|
|
extern char *
|
|
get_dest_name(const char *src_name)
|
|
{
|
|
return opt_mode == MODE_COMPRESS
|
|
? compressed_name(src_name)
|
|
: uncompressed_name(src_name);
|
|
}
|