Пример #1
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 size_t src_len)
{
	static const struct {
		const char *compressed;
		const char *uncompressed;
	} suffixes[] = {
		{ ".xz",    "" },
		{ ".txz",   ".tar" }, // .txz abbreviation for .txt.gz is rare.
		{ ".lzma",  "" },
		{ ".tlz",   ".tar" },
		// { ".gz",    "" },
		// { ".tgz",   ".tar" },
	};

	const char *new_suffix = "";
	size_t new_len = 0;

	if (opt_format == FORMAT_RAW) {
		// Don't check for known suffixes when --format=raw was used.
		if (custom_suffix == NULL) {
			message_error(_("%s: With --format=raw, "
					"--suffix=.SUF is required unless "
					"writing to stdout"), src_name);
			return NULL;
		}
	} else {
		for (size_t i = 0; i < ARRAY_SIZE(suffixes); ++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 && custom_suffix != NULL)
		new_len = test_suffix(custom_suffix, src_name, src_len);

	if (new_len == 0) {
		message_warning(_("%s: Filename has an unknown suffix, "
				"skipping"), src_name);
		return NULL;
	}

	const size_t new_suffix_len = strlen(new_suffix);
	char *dest_name = xmalloc(new_len + new_suffix_len + 1);

	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;
}
Пример #2
0
int main(int, char**) {
  plan_tests(69);
  test_integrals();
  test_strings();
  test_pointers();
  test_double();
  test_concat();
  test_suffix();
  test_to();
  test_path_cat();
  test_basename_dirname();
  test_operator();
  test_split();

  return exit_status();
}
Пример #3
0
/// \brief      Appends suffix to src_name
///
/// In contrast to uncompressed_name(), we check only suffixes that are valid
/// for the specified file format.
static char *
compressed_name(const char *src_name, const size_t src_len)
{
	// The order of these must match the order in args.h.
	static const char *const all_suffixes[][3] = {
		{
			".xz",
			".txz",
			NULL
		}, {
			".lzma",
			".tlz",
			NULL
/*
		}, {
			".gz",
			".tgz",
			NULL
*/
		}, {
			// --format=raw requires specifying the suffix
			// manually or using stdout.
			NULL
		}
	};

	// args.c ensures this.
	assert(opt_format != FORMAT_AUTO);

	const size_t format = opt_format - 1;
	const char *const *suffixes = all_suffixes[format];

	for (size_t i = 0; suffixes[i] != NULL; ++i) {
		if (test_suffix(suffixes[i], src_name, src_len) != 0) {
			message_warning(_("%s: File already has `%s' "
					"suffix, skipping"), src_name,
					suffixes[i]);
			return NULL;
		}
	}

	if (custom_suffix != NULL) {
		if (test_suffix(custom_suffix, src_name, src_len) != 0) {
			message_warning(_("%s: File already has `%s' "
					"suffix, skipping"), src_name,
					custom_suffix);
			return NULL;
		}
	}

	// TODO: Hmm, maybe it would be better to validate this in args.c,
	// since the suffix handling when decoding is weird now.
	if (opt_format == FORMAT_RAW && custom_suffix == NULL) {
		message_error(_("%s: With --format=raw, "
				"--suffix=.SUF is required unless "
				"writing to stdout"), src_name);
		return NULL;
	}

	const char *suffix = custom_suffix != NULL
			? custom_suffix : suffixes[0];
	const size_t suffix_len = strlen(suffix);

	char *dest_name = xmalloc(src_len + suffix_len + 1);

	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;
}
Пример #4
0
/// \brief      Appends suffix to src_name
///
/// In contrast to uncompressed_name(), we check only suffixes that are valid
/// for the specified file format.
static char *
compressed_name(const char *src_name, size_t src_len)
{
	// The order of these must match the order in args.h.
	static const char *const all_suffixes[][4] = {
		{
			".xz",
			".txz",
			NULL
		}, {
			".lzma",
#ifdef __DJGPP__
			".lzm",
#endif
			".tlz",
			NULL
/*
		}, {
			".gz",
			".tgz",
			NULL
*/
		}, {
			// --format=raw requires specifying the suffix
			// manually or using stdout.
			NULL
		}
	};

	// args.c ensures this.
	assert(opt_format != FORMAT_AUTO);

	const size_t format = opt_format - 1;
	const char *const *suffixes = all_suffixes[format];

	// Look for known filename suffixes and refuse to compress them.
	for (size_t i = 0; suffixes[i] != NULL; ++i) {
		if (test_suffix(suffixes[i], src_name, src_len) != 0) {
			msg_suffix(src_name, suffixes[i]);
			return NULL;
		}
	}

#ifdef __DJGPP__
	// Recognize also the special suffix that is used when long
	// filename (LFN) support isn't available. This suffix is
	// recognized on LFN systems too.
	if (opt_format == FORMAT_XZ && has_sfn_suffix(src_name, src_len)) {
		msg_suffix(src_name, "-");
		return NULL;
	}
#endif

	if (custom_suffix != NULL) {
		if (test_suffix(custom_suffix, src_name, src_len) != 0) {
			msg_suffix(src_name, custom_suffix);
			return NULL;
		}
	}

	// TODO: Hmm, maybe it would be better to validate this in args.c,
	// since the suffix handling when decoding is weird now.
	if (opt_format == FORMAT_RAW && custom_suffix == NULL) {
		message_error(_("%s: With --format=raw, "
				"--suffix=.SUF is required unless "
				"writing to stdout"), src_name);
		return NULL;
	}

	const char *suffix = custom_suffix != NULL
			? custom_suffix : suffixes[0];
	size_t suffix_len = strlen(suffix);

#ifdef __DJGPP__
	if (!_use_lfn(src_name)) {
		// Long filename (LFN) support isn't available and we are
		// limited to 8.3 short filenames (SFN).
		//
		// Look for suffix separator from the filename, and make sure
		// that it is in the filename, not in a directory name.
		const char *sufsep = strrchr(src_name, '.');
		if (sufsep == NULL || sufsep[1] == '\0'
				|| has_dir_sep(sufsep)) {
			// src_name has no filename extension.
			//
			// Examples:
			// xz foo         -> foo.xz
			// xz -F lzma foo -> foo.lzm
			// xz -S x foo    -> foox
			// xz -S x foo.   -> foo.x
			// xz -S x.y foo  -> foox.y
			// xz -S .x foo   -> foo.x
			// xz -S .x foo.  -> foo.x
			//
			// Avoid double dots:
			if (sufsep != NULL && sufsep[1] == '\0'
					&& suffix[0] == '.')
				--src_len;

		} else if (custom_suffix == NULL
				&& strcasecmp(sufsep, ".tar") == 0) {
			// ".tar" is handled specially.
			//
			// Examples:
			// xz foo.tar          -> foo.txz
			// xz -F lzma foo.tar  -> foo.tlz
			static const char *const tar_suffixes[] = {
				".txz",
				".tlz",
				// ".tgz",
			};
			suffix = tar_suffixes[format];
			suffix_len = 4;
			src_len -= 4;

		} else {
			if (custom_suffix == NULL && opt_format == FORMAT_XZ) {
				// Instead of the .xz suffix, use a single
				// character at the end of the filename
				// extension. This is to minimize name
				// conflicts when compressing multiple files
				// with the same basename. E.g. foo.txt and
				// foo.exe become foo.tx- and foo.ex-. Dash
				// is rare as the last character of the
				// filename extension, so it seems to be
				// quite safe choice and it stands out better
				// in directory listings than e.g. x. For
				// comparison, gzip uses z.
				suffix = "-";
				suffix_len = 1;
			}

			if (suffix[0] == '.') {
				// The first character of the suffix is a dot.
				// Throw away the original filename extension
				// and replace it with the new suffix.
				//
				// Examples:
				// xz -F lzma foo.txt  -> foo.lzm
				// xz -S .x  foo.txt   -> foo.x
				src_len = sufsep - src_name;

			} else {
				// The first character of the suffix is not
				// a dot. Preserve the first 0-2 characters
				// of the original filename extension.
				//
				// Examples:
				// xz foo.txt         -> foo.tx-
				// xz -S x  foo.c     -> foo.cx
				// xz -S ab foo.c     -> foo.cab
				// xz -S ab foo.txt   -> foo.tab
				// xz -S abc foo.txt  -> foo.abc
				//
				// Truncate the suffix to three chars:
				if (suffix_len > 3)
					suffix_len = 3;

				// If needed, overwrite 1-3 characters.
				if (strlen(sufsep) > 4 - suffix_len)
					src_len = sufsep - src_name
							+ 4 - suffix_len;
			}
		}
	}
#endif

	char *dest_name = xmalloc(src_len + suffix_len + 1);

	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;
}
Пример #5
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 size_t src_len)
{
	static const struct {
		const char *compressed;
		const char *uncompressed;
	} suffixes[] = {
		{ ".xz",    "" },
		{ ".txz",   ".tar" }, // .txz abbreviation for .txt.gz is rare.
		{ ".lzma",  "" },
#ifdef __DJGPP__
		{ ".lzm",   "" },
#endif
		{ ".tlz",   ".tar" },
		// { ".gz",    "" },
		// { ".tgz",   ".tar" },
	};

	const char *new_suffix = "";
	size_t new_len = 0;

	if (opt_format == FORMAT_RAW) {
		// Don't check for known suffixes when --format=raw was used.
		if (custom_suffix == NULL) {
			message_error(_("%s: With --format=raw, "
					"--suffix=.SUF is required unless "
					"writing to stdout"), src_name);
			return NULL;
		}
	} else {
		for (size_t i = 0; i < ARRAY_SIZE(suffixes); ++i) {
			new_len = test_suffix(suffixes[i].compressed,
					src_name, src_len);
			if (new_len != 0) {
				new_suffix = suffixes[i].uncompressed;
				break;
			}
		}

#ifdef __DJGPP__
		// Support also *.?- -> *.? and *.??- -> *.?? on DOS.
		// This is done also when long filenames are available
		// to keep it easy to decompress files created when
		// long filename support wasn't available.
		if (new_len == 0 && has_sfn_suffix(src_name, src_len)) {
			new_suffix = "";
			new_len = src_len - 1;
		}
#endif
	}

	if (new_len == 0 && custom_suffix != NULL)
		new_len = test_suffix(custom_suffix, src_name, src_len);

	if (new_len == 0) {
		message_warning(_("%s: Filename has an unknown suffix, "
				"skipping"), src_name);
		return NULL;
	}

	const size_t new_suffix_len = strlen(new_suffix);
	char *dest_name = xmalloc(new_len + new_suffix_len + 1);

	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;
}