aboutsummaryrefslogtreecommitdiff
path: root/src/lzma/suffix.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lzma/suffix.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/lzma/suffix.c b/src/lzma/suffix.c
new file mode 100644
index 00000000..57afce82
--- /dev/null
+++ b/src/lzma/suffix.c
@@ -0,0 +1,145 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \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);
+}