aboutsummaryrefslogblamecommitdiff
path: root/src/lzma/suffix.c
blob: 57afce82c3d511528bd37006c9040a58f40e58eb (plain) (tree)
















































































































































                                                                               
///////////////////////////////////////////////////////////////////////////////
//
/// \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);
}