aboutsummaryrefslogtreecommitdiff
path: root/src/xz
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2009-09-19 09:47:30 +0300
committerLasse Collin <lasse.collin@tukaani.org>2009-09-19 09:47:30 +0300
commite599bba4216c0edb8cc8f40adad3a6dba88685f4 (patch)
treed52c699f599e276ff65302e5854a26998da1a928 /src/xz
parentFix incorrect use of "restrict". (diff)
downloadxz-e599bba4216c0edb8cc8f40adad3a6dba88685f4.tar.xz
Various changes.
Separate a few reusable components from XZ Utils specific code. The reusable code is now in "tuklib" modules. A few more could be separated still, e.g. bswap.h. Fix some bugs in lzmainfo. Fix physmem and cpucores code on OS/2. Thanks to Elbert Pol for help. Add OpenVMS support into physmem. Add a few #ifdefs to ease building XZ Utils on OpenVMS. Thanks to Jouk Jansen for the original patch.
Diffstat (limited to 'src/xz')
-rw-r--r--src/xz/Makefile.am7
-rw-r--r--src/xz/args.c8
-rw-r--r--src/xz/file_io.c43
-rw-r--r--src/xz/hardware.c8
-rw-r--r--src/xz/main.c100
-rw-r--r--src/xz/main.h7
-rw-r--r--src/xz/message.c30
-rw-r--r--src/xz/message.h8
-rw-r--r--src/xz/private.h11
-rw-r--r--src/xz/signals.c2
-rw-r--r--src/xz/signals.h17
-rw-r--r--src/xz/suffix.c2
12 files changed, 88 insertions, 155 deletions
diff --git a/src/xz/Makefile.am b/src/xz/Makefile.am
index 9f4b4668..cc617053 100644
--- a/src/xz/Makefile.am
+++ b/src/xz/Makefile.am
@@ -28,7 +28,12 @@ xz_SOURCES = \
suffix.c \
suffix.h \
util.c \
- util.h
+ util.h \
+ $(top_srcdir)/src/common/tuklib_open_stdxxx.c \
+ $(top_srcdir)/src/common/tuklib_progname.c \
+ $(top_srcdir)/src/common/tuklib_exit.c \
+ $(top_srcdir)/src/common/tuklib_physmem.c \
+ $(top_srcdir)/src/common/tuklib_cpucores.c
if COND_W32
xz_SOURCES += xz_w32res.rc
diff --git a/src/xz/args.c b/src/xz/args.c
index b50e28b7..b35a5b63 100644
--- a/src/xz/args.c
+++ b/src/xz/args.c
@@ -351,7 +351,7 @@ parse_real(args_info *args, int argc, char **argv)
default:
message_try_help();
- my_exit(E_ERROR);
+ tuklib_exit(E_ERROR, E_ERROR, false);
}
}
@@ -449,18 +449,12 @@ args_parse(args_info *args, int argc, char **argv)
// Check how we were called.
{
-#ifdef DOSLIKE
- // We adjusted argv[0] in the beginning of main() so we don't
- // need to do anything here.
- const char *name = argv[0];
-#else
// Remove the leading path name, if any.
const char *name = strrchr(argv[0], '/');
if (name == NULL)
name = argv[0];
else
++name;
-#endif
// NOTE: It's possible that name[0] is now '\0' if argv[0]
// is weird, but it doesn't matter here.
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
index 4c52da56..a7863d27 100644
--- a/src/xz/file_io.c
+++ b/src/xz/file_io.c
@@ -14,8 +14,10 @@
#include <fcntl.h>
-#ifdef DOSLIKE
+#ifdef TUKLIB_DOSLIKE
# include <io.h>
+#else
+static bool warn_fchown;
#endif
#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
@@ -24,6 +26,8 @@
# include <utime.h>
#endif
+#include "tuklib_open_stdxxx.h"
+
#ifndef O_BINARY
# define O_BINARY 0
#endif
@@ -32,22 +36,17 @@
# define O_NOCTTY 0
#endif
-#ifndef DOSLIKE
-# include "open_stdxxx.h"
-static bool warn_fchown;
-#endif
-
extern void
io_init(void)
{
-#ifndef DOSLIKE
// Make sure that stdin, stdout, and and stderr are connected to
// a valid file descriptor. Exit immediatelly with exit code ERROR
// if we cannot make the file descriptors valid. Maybe we should
// print an error message, but our stderr could be screwed anyway.
- open_stdxxx(E_ERROR);
+ tuklib_open_stdxxx(E_ERROR);
+#ifndef TUKLIB_DOSLIKE
// If fchown() fails setting the owner, we warn about it only if
// we are root.
warn_fchown = geteuid() == 0;
@@ -64,7 +63,7 @@ io_init(void)
}
-/// \brief Unlinks a file
+/// \brief Unlink a file
///
/// This tries to verify that the file being unlinked really is the file that
/// we want to unlink by verifying device and inode numbers. There's still
@@ -73,9 +72,9 @@ io_init(void)
static void
io_unlink(const char *name, const struct stat *known_st)
{
-#ifdef DOSLIKE
- // On Windows, st_ino is meaningless, so don't bother testing it.
- // Just silence a compiler warning.
+#if defined(TUKLIB_DOSLIKE) || defined(__VMS)
+ // On DOS-like systems, st_ino is meaningless, so don't bother
+ // testing it. Just silence a compiler warning.
(void)known_st;
#else
struct stat new_st;
@@ -105,7 +104,7 @@ static void
io_copy_attrs(const file_pair *pair)
{
// Skip chown and chmod on Windows.
-#ifndef DOSLIKE
+#ifndef TUKLIB_DOSLIKE
// This function is more tricky than you may think at first.
// Blindly copying permissions may permit users to access the
// destination file who didn't have permission to access the
@@ -240,7 +239,7 @@ io_open_src(file_pair *pair)
// There's nothing to open when reading from stdin.
if (pair->src_name == stdin_filename) {
pair->src_fd = STDIN_FILENO;
-#ifdef DOSLIKE
+#ifdef TUKLIB_DOSLIKE
setmode(STDIN_FILENO, O_BINARY);
#endif
return false;
@@ -253,7 +252,7 @@ io_open_src(file_pair *pair)
// Flags for open()
int flags = O_RDONLY | O_BINARY | O_NOCTTY;
-#ifndef DOSLIKE
+#ifndef TUKLIB_DOSLIKE
// If we accept only regular files, we need to be careful to avoid
// problems with special files like devices and FIFOs. O_NONBLOCK
// prevents blocking when opening such files. When we want to accept
@@ -266,7 +265,7 @@ io_open_src(file_pair *pair)
#if defined(O_NOFOLLOW)
if (reg_files_only)
flags |= O_NOFOLLOW;
-#elif !defined(DOSLIKE)
+#elif !defined(TUKLIB_DOSLIKE)
// Some POSIX-like systems lack O_NOFOLLOW (it's not required
// by POSIX). Check for symlinks with a separate lstat() on
// these systems.
@@ -370,7 +369,7 @@ io_open_src(file_pair *pair)
return true;
}
-#ifndef DOSLIKE
+#ifndef TUKLIB_DOSLIKE
// Drop O_NONBLOCK, which is used only when we are accepting only
// regular files. After the open() call, we want things to block
// instead of giving EAGAIN.
@@ -405,7 +404,7 @@ io_open_src(file_pair *pair)
}
// These are meaningless on Windows.
-#ifndef DOSLIKE
+#ifndef TUKLIB_DOSLIKE
if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
// gzip rejects setuid and setgid files even
// when --force was used. bzip2 doesn't check
@@ -457,7 +456,7 @@ static void
io_close_src(file_pair *pair, bool success)
{
if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
-#ifdef DOSLIKE
+#ifdef TUKLIB_DOSLIKE
(void)close(pair->src_fd);
#endif
@@ -471,7 +470,7 @@ io_close_src(file_pair *pair, bool success)
if (success && !opt_keep_original)
io_unlink(pair->src_name, &pair->src_st);
-#ifndef DOSLIKE
+#ifndef TUKLIB_DOSLIKE
(void)close(pair->src_fd);
#endif
}
@@ -487,7 +486,7 @@ io_open_dest(file_pair *pair)
// We don't modify or free() this.
pair->dest_name = (char *)"(stdout)";
pair->dest_fd = STDOUT_FILENO;
-#ifdef DOSLIKE
+#ifdef TUKLIB_DOSLIKE
setmode(STDOUT_FILENO, O_BINARY);
#endif
return false;
@@ -531,7 +530,9 @@ io_open_dest(file_pair *pair)
// If this really fails... well, we have a safe fallback.
if (fstat(pair->dest_fd, &pair->dest_st)) {
pair->dest_st.st_dev = 0;
+#ifndef __VMS
pair->dest_st.st_ino = 0;
+#endif
}
return false;
diff --git a/src/xz/hardware.c b/src/xz/hardware.c
index 72dc2cb1..cb094abd 100644
--- a/src/xz/hardware.c
+++ b/src/xz/hardware.c
@@ -11,8 +11,8 @@
///////////////////////////////////////////////////////////////////////////////
#include "private.h"
-#include "physmem.h"
-#include "cpucores.h"
+#include "tuklib_physmem.h"
+#include "tuklib_cpucores.h"
/// Maximum number of free *coder* threads. This can be set with
@@ -28,7 +28,7 @@ hardware_threadlimit_set(uint32_t new_threadlimit)
{
if (new_threadlimit == 0) {
// The default is the number of available CPU cores.
- threadlimit = cpucores();
+ threadlimit = tuklib_cpucores();
if (threadlimit == 0)
threadlimit = 1;
} else {
@@ -66,7 +66,7 @@ hardware_memlimit_set_percentage(uint32_t percentage)
assert(percentage > 0);
assert(percentage <= 100);
- uint64_t mem = physmem();
+ uint64_t mem = tuklib_physmem();
// If we cannot determine the amount of RAM, assume 32 MiB. Maybe
// even that is too much on some systems. But on most systems it's
diff --git a/src/xz/main.c b/src/xz/main.c
index 4121f8d4..3295bba3 100644
--- a/src/xz/main.c
+++ b/src/xz/main.c
@@ -42,47 +42,6 @@ set_exit_no_warn(void)
}
-extern void
-my_exit(enum exit_status_type status)
-{
- // Close stdout. If something goes wrong, print an error message
- // to stderr.
- {
- const int ferror_err = ferror(stdout);
- const int fclose_err = fclose(stdout);
- if (ferror_err || fclose_err) {
- // If it was fclose() that failed, we have the reason
- // in errno. If only ferror() indicated an error,
- // we have no idea what the reason was.
- message(V_ERROR, "%s: %s", _("Writing to standard "
- "output failed"),
- fclose_err ? strerror(errno)
- : _("Unknown error"));
- status = E_ERROR;
- }
- }
-
- // Close stderr. If something goes wrong, there's nothing where we
- // could print an error message. Just set the exit status.
- {
- const int ferror_err = ferror(stderr);
- const int fclose_err = fclose(stderr);
- if (fclose_err || ferror_err)
- status = E_ERROR;
- }
-
- // Suppress the exit status indicating a warning if --no-warn
- // was specified.
- if (status == E_WARNING && no_warn)
- status = E_SUCCESS;
-
- // If we have got a signal, raise it to kill the program.
- // Otherwise we just call exit().
- signals_exit();
- exit(status);
-}
-
-
static const char *
read_name(const args_info *args)
{
@@ -170,45 +129,18 @@ read_name(const args_info *args)
int
main(int argc, char **argv)
{
- // Initialize the file I/O as the very first step. This makes sure
- // that stdin, stdout, and stderr are something valid.
- io_init();
+ // Set up the progname variable.
+ tuklib_progname_init(argv);
-#ifdef DOSLIKE
- // Adjust argv[0] to make it look nicer in messages, and also to
- // help the code in args.c.
- {
- // Strip the leading path.
- char *p = argv[0] + strlen(argv[0]);
- while (argv[0] < p && p[-1] != '/' && p[-1] != '\\')
- --p;
-
- argv[0] = p;
-
- // Strip the .exe suffix.
- p = strrchr(p, '.');
- if (p != NULL)
- *p = '\0';
-
- // Make it lowercase.
- for (p = argv[0]; *p != '\0'; ++p)
- if (*p >= 'A' && *p <= 'Z')
- *p = *p - 'A' + 'a';
- }
-#endif
-
- // Set up the locale.
- setlocale(LC_ALL, "");
+ // Initialize the file I/O. This makes sure that
+ // stdin, stdout, and stderr are something valid.
+ io_init();
-#ifdef ENABLE_NLS
- // Set up the message translations too.
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-#endif
+ // Set up the locale and message translations.
+ tuklib_gettext_init(PACKAGE, LOCALEDIR);
- // Set the program invocation name used in various messages, and
- // do other message handling related initializations.
- message_init(argv[0]);
+ // Initialize handling of error/warning/other messages.
+ message_init();
// Set hardware-dependent default values. These can be overriden
// on the command line, thus this must be done before parse_args().
@@ -235,7 +167,7 @@ main(int argc, char **argv)
&& strcmp(args.arg_names[0], "-") == 0)) {
if (is_tty_stdout()) {
message_try_help();
- my_exit(E_ERROR);
+ tuklib_exit(E_ERROR, E_ERROR, false);
}
}
}
@@ -308,5 +240,15 @@ main(int argc, char **argv)
(void)fclose(args.files_file);
}
- my_exit(exit_status);
+ // If we have got a signal, raise it to kill the program instead
+ // of calling tuklib_exit().
+ signals_exit();
+
+ // Suppress the exit status indicating a warning if --no-warn
+ // was specified.
+ if (exit_status == E_WARNING && no_warn)
+ exit_status = E_SUCCESS;
+
+ tuklib_exit(exit_status, E_ERROR,
+ message_verbosity_get() != V_SILENT);
}
diff --git a/src/xz/main.h b/src/xz/main.h
index 8fd92393..5622cebb 100644
--- a/src/xz/main.h
+++ b/src/xz/main.h
@@ -28,10 +28,3 @@ extern void set_exit_status(enum exit_status_type new_status);
/// but nothing worth an error has occurred. This is called when --no-warn
/// is specified.
extern void set_exit_no_warn(void);
-
-
-/// Exits the program using the given status. This takes care of closing
-/// stdin, stdout, and stderr and catches possible errors. If we had got
-/// a signal, this function will raise it so that to the parent process it
-/// appears that we were killed by the signal sent by the user.
-extern void my_exit(enum exit_status_type status) lzma_attribute((noreturn));
diff --git a/src/xz/message.c b/src/xz/message.c
index 0a01bc45..991fa7d4 100644
--- a/src/xz/message.c
+++ b/src/xz/message.c
@@ -19,9 +19,6 @@
#include <stdarg.h>
-/// Name of the program which is prefixed to the error messages.
-static const char *argv0;
-
/// Number of the current file
static unsigned int files_pos = 0;
@@ -138,11 +135,8 @@ my_snprintf(char **pos, size_t *left, const char *fmt, ...)
extern void
-message_init(const char *given_argv0)
+message_init(void)
{
- // Name of the program
- argv0 = given_argv0;
-
// If --verbose is used, we use a progress indicator if and only
// if stderr is a terminal. If stderr is not a terminal, we print
// verbose information only after finishing the file. As a special
@@ -226,6 +220,13 @@ message_verbosity_decrease(void)
}
+extern enum message_verbosity
+message_verbosity_get(void)
+{
+ return verbosity;
+}
+
+
extern void
message_set_files(unsigned int files)
{
@@ -774,7 +775,7 @@ vmessage(enum message_verbosity v, const char *fmt, va_list ap)
progress_flush(false);
- fprintf(stderr, "%s: ", argv0);
+ fprintf(stderr, "%s: ", progname);
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
@@ -830,7 +831,7 @@ message_fatal(const char *fmt, ...)
vmessage(V_ERROR, fmt, ap);
va_end(ap);
- my_exit(E_ERROR);
+ tuklib_exit(E_ERROR, E_ERROR, false);
}
@@ -894,7 +895,7 @@ message_filters(enum message_verbosity v, const lzma_filter *filters)
if (v > verbosity)
return;
- fprintf(stderr, _("%s: Filter chain:"), argv0);
+ fprintf(stderr, _("%s: Filter chain:"), progname);
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
fprintf(stderr, " --");
@@ -1005,7 +1006,8 @@ message_try_help(void)
{
// Print this with V_WARNING instead of V_ERROR to prevent it from
// showing up when --quiet has been specified.
- message(V_WARNING, _("Try `%s --help' for more information."), argv0);
+ message(V_WARNING, _("Try `%s --help' for more information."),
+ progname);
return;
}
@@ -1017,7 +1019,7 @@ message_version(void)
// line tool version, so print both.
printf("xz (" PACKAGE_NAME ") " LZMA_VERSION_STRING "\n");
printf("liblzma %s\n", lzma_version_string());
- my_exit(E_SUCCESS);
+ tuklib_exit(E_SUCCESS, E_ERROR, verbosity != V_SILENT);
}
@@ -1026,7 +1028,7 @@ message_help(bool long_help)
{
printf(_("Usage: %s [OPTION]... [FILE]...\n"
"Compress or decompress FILEs in the .xz format.\n\n"),
- argv0);
+ progname);
puts(_("Mandatory arguments to long options are mandatory for "
"short options too.\n"));
@@ -1168,5 +1170,5 @@ message_help(bool long_help)
PACKAGE_BUGREPORT);
printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_HOMEPAGE);
- my_exit(E_SUCCESS);
+ tuklib_exit(E_SUCCESS, E_ERROR, verbosity != V_SILENT);
}
diff --git a/src/xz/message.h b/src/xz/message.h
index 16e38b75..2b1ab919 100644
--- a/src/xz/message.h
+++ b/src/xz/message.h
@@ -22,12 +22,9 @@ enum message_verbosity {
/// \brief Initializes the message functions
///
-/// \param argv0 Name of the program i.e. argv[0] from main()
-/// \param verbosity Verbosity level
-///
/// If an error occurs, this function doesn't return.
///
-extern void message_init(const char *argv0);
+extern void message_init(void);
/// Increase verbosity level by one step unless it was at maximum.
@@ -36,6 +33,9 @@ extern void message_verbosity_increase(void);
/// Decrease verbosity level by one step unless it was at minimum.
extern void message_verbosity_decrease(void);
+/// Get the current verbosity level.
+extern enum message_verbosity message_verbosity_get(void);
+
/// Set the total number of files to be processed (stdin is counted as a file
/// here). The default is one.
diff --git a/src/xz/private.h b/src/xz/private.h
index 6141b88c..8d9ce978 100644
--- a/src/xz/private.h
+++ b/src/xz/private.h
@@ -22,14 +22,9 @@
#include <stdio.h>
#include <unistd.h>
-#ifdef ENABLE_NLS
-# include <libintl.h>
-# define _(msgid) gettext(msgid)
-# define N_(msgid1, msgid2, n) ngettext(msgid1, msgid2, n)
-#else
-# define _(msgid) (msgid)
-# define N_(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
-#endif
+#include "tuklib_gettext.h"
+#include "tuklib_progname.h"
+#include "tuklib_exit.h"
#ifndef STDIN_FILENO
# define STDIN_FILENO (fileno(stdin))
diff --git a/src/xz/signals.c b/src/xz/signals.c
index c9acab26..ab60488f 100644
--- a/src/xz/signals.c
+++ b/src/xz/signals.c
@@ -95,6 +95,7 @@ signals_init(void)
}
+#ifndef __VMS
extern void
signals_block(void)
{
@@ -121,6 +122,7 @@ signals_unblock(void)
return;
}
+#endif
extern void
diff --git a/src/xz/signals.h b/src/xz/signals.h
index 48945b22..7603d803 100644
--- a/src/xz/signals.h
+++ b/src/xz/signals.h
@@ -21,8 +21,10 @@ extern volatile sig_atomic_t user_abort;
extern void signals_init(void);
-#ifndef _WIN32
-
+#if defined(_WIN32) || defined(__VMS)
+# define signals_block() do { } while (0)
+# define signals_unblock() do { } while (0)
+#else
/// Block the signals which don't have SA_RESTART and which would just set
/// user_abort to true. This is handy when we don't want to handle EINTR
/// and don't want SA_RESTART either.
@@ -30,15 +32,12 @@ extern void signals_block(void);
/// Unblock the signals blocked by signals_block().
extern void signals_unblock(void);
+#endif
+#ifdef _WIN32
+# define signals_exit() do { } while (0)
+#else
/// If user has sent us a signal earlier to terminate the process,
/// re-raise that signal to actually terminate the process.
extern void signals_exit(void);
-
-#else
-
-#define signals_block() do { } while (0)
-#define signals_unblock() do { } while (0)
-#define signals_exit() do { } while (0)
-
#endif
diff --git a/src/xz/suffix.c b/src/xz/suffix.c
index f9052832..f2a2da27 100644
--- a/src/xz/suffix.c
+++ b/src/xz/suffix.c
@@ -13,7 +13,7 @@
#include "private.h"
// For case-insensitive filename suffix on case-insensitive systems
-#ifdef DOSLIKE
+#if defined(TUKLIB_DOSLIKE) || defined(__VMS)
# define strcmp strcasecmp
#endif