Fix bad pointer usage in xsparse.c
[tar.git] / src / suffix.c
blobaf78de5d96be4cbb5590d1cf30908cadd16c3d35
1 /* This file is part of GNU tar.
2 Copyright 2007-2024 Free Software Foundation, Inc.
4 Written by Sergey Poznyakoff.
6 GNU tar is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any later
9 version.
11 GNU tar is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
16 You should have received a copy of the GNU General Public License along
17 with GNU tar. If not, see <http://www.gnu.org/licenses/>. */
19 #include <system.h>
20 #include "common.h"
22 struct compression_suffix
24 char suffix[sizeof "tbz2"]; /* "tbz2" is tied for longest. */
25 char program[max (max (max (sizeof GZIP_PROGRAM, sizeof COMPRESS_PROGRAM),
26 max (sizeof BZIP2_PROGRAM, sizeof LZIP_PROGRAM)),
27 max (max (sizeof LZMA_PROGRAM, sizeof LZOP_PROGRAM),
28 max (sizeof XZ_PROGRAM, sizeof ZSTD_PROGRAM)))];
31 static struct compression_suffix const compression_suffixes[] = {
32 #define __CAT2__(a,b) a ## b
33 #define S(s, p) #s, __CAT2__(p,_PROGRAM)
34 { "tar", "" },
35 { S(gz, GZIP) },
36 { S(z, GZIP) },
37 { S(tgz, GZIP) },
38 { S(taz, GZIP) },
39 { S(Z, COMPRESS) },
40 { S(taZ, COMPRESS) },
41 { S(bz2, BZIP2) },
42 { S(tbz, BZIP2) },
43 { S(tbz2, BZIP2) },
44 { S(tz2, BZIP2) },
45 { S(lz, LZIP) },
46 { S(lzma, LZMA) },
47 { S(tlz, LZMA) },
48 { S(lzo, LZOP) },
49 { S(tzo, LZOP) },
50 { S(xz, XZ) },
51 { S(txz, XZ) }, /* Slackware */
52 { S(zst, ZSTD) },
53 { S(tzst, ZSTD) },
54 #undef S
55 #undef __CAT2__
58 /* Extract the suffix from archive file NAME, and return a pointer to
59 compression_suffix associated with it or NULL if none is found.
60 No matter what is the return value, if RET_LEN is not NULL, store
61 there the length of NAME with that suffix stripped, or 0 if NAME has
62 no suffix. */
63 static struct compression_suffix const *
64 find_compression_suffix (char const *name, idx_t *ret_len)
66 char const *suf = strrchr (name, '.');
68 if (suf && suf[1] != 0 && suf[1] != '/')
70 if (ret_len)
71 *ret_len = suf - name;
72 suf++;
74 for (struct compression_suffix const *p = compression_suffixes;
75 p < (compression_suffixes
76 + sizeof compression_suffixes / sizeof *compression_suffixes);
77 p++)
78 if (strcmp (p->suffix, suf) == 0)
79 return p;
81 else if (ret_len)
82 *ret_len = 0;
83 return NULL;
86 /* Select compression program using the suffix of the archive file NAME.
87 Use DEFPROG, if there is no suffix, or if no program is associated with
88 the suffix. In the latter case, if VERBOSE is true, issue a warning.
90 void
91 set_compression_program_by_suffix (const char *name, const char *defprog,
92 bool verbose)
94 idx_t len;
95 struct compression_suffix const *p = find_compression_suffix (name, &len);
96 if (p)
97 use_compress_program_option = p->program[0] ? p->program : NULL;
98 else
100 use_compress_program_option = defprog;
101 if (len > 0 && verbose)
102 paxwarn (0,
103 _("no compression program is defined for suffix '%s';"
104 " assuming %s"),
105 name + len,
106 defprog ? defprog : "uncompressed archive");
110 char *
111 strip_compression_suffix (const char *name)
113 char *s = NULL;
114 idx_t len;
115 struct compression_suffix const *p = find_compression_suffix (name, &len);
117 if (p)
119 /* Strip an additional ".tar" suffix, but only if the just-stripped
120 "outer" suffix did not begin with "t". */
121 if (len > 4 && strncmp (name + len - 4, ".tar", 4) == 0
122 && p->suffix[0] != 't')
123 len -= 4;
124 if (len == 0)
125 return NULL;
126 s = xmalloc (len + 1);
127 memcpy (s, name, len);
128 s[len] = 0;
130 return s;