diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2009-09-19 09:47:30 +0300 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2009-09-19 09:47:30 +0300 |
commit | e599bba4216c0edb8cc8f40adad3a6dba88685f4 (patch) | |
tree | d52c699f599e276ff65302e5854a26998da1a928 /src/xz | |
parent | Fix incorrect use of "restrict". (diff) | |
download | xz-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.am | 7 | ||||
-rw-r--r-- | src/xz/args.c | 8 | ||||
-rw-r--r-- | src/xz/file_io.c | 43 | ||||
-rw-r--r-- | src/xz/hardware.c | 8 | ||||
-rw-r--r-- | src/xz/main.c | 100 | ||||
-rw-r--r-- | src/xz/main.h | 7 | ||||
-rw-r--r-- | src/xz/message.c | 30 | ||||
-rw-r--r-- | src/xz/message.h | 8 | ||||
-rw-r--r-- | src/xz/private.h | 11 | ||||
-rw-r--r-- | src/xz/signals.c | 2 | ||||
-rw-r--r-- | src/xz/signals.h | 17 | ||||
-rw-r--r-- | src/xz/suffix.c | 2 |
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 |