mirror of
https://git.tukaani.org/xz.git
synced 2024-04-04 12:36:23 +02:00
Various code cleanups the the xz command line tool.
It now builds with MinGW.
This commit is contained in:
parent
d0c0b9e94e
commit
75905a9afc
18 changed files with 399 additions and 246 deletions
|
@ -27,6 +27,13 @@
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# ifndef _WIN32_WINNT
|
||||||
|
# define _WIN32_WINNT 0x0500
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// \brief Get the amount of physical memory in bytes
|
/// \brief Get the amount of physical memory in bytes
|
||||||
///
|
///
|
||||||
|
@ -62,6 +69,12 @@ physmem(void)
|
||||||
ret = mem;
|
ret = mem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
MEMORYSTATUSEX meminfo;
|
||||||
|
meminfo.dwLength = sizeof(meminfo);
|
||||||
|
if (GlobalMemoryStatusEx(&meminfo))
|
||||||
|
ret = meminfo.ullTotalPhys;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -30,6 +30,8 @@ xz_SOURCES = \
|
||||||
private.h \
|
private.h \
|
||||||
process.c \
|
process.c \
|
||||||
process.h \
|
process.h \
|
||||||
|
signals.c \
|
||||||
|
signals.h \
|
||||||
suffix.c \
|
suffix.c \
|
||||||
suffix.h \
|
suffix.h \
|
||||||
util.c \
|
util.c \
|
||||||
|
|
|
@ -17,12 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef ARGS_H
|
|
||||||
#define ARGS_H
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/// Filenames from command line
|
/// Filenames from command line
|
||||||
char **arg_names;
|
char **arg_names;
|
||||||
|
@ -52,5 +46,3 @@ extern bool opt_keep_original;
|
||||||
extern const char *stdin_filename;
|
extern const char *stdin_filename;
|
||||||
|
|
||||||
extern void args_parse(args_info *args, int argc, char **argv);
|
extern void args_parse(args_info *args, int argc, char **argv);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
/// \file hardware.c
|
/// \file hardware.h
|
||||||
/// \brief Detection of available hardware resources
|
/// \brief Detection of available hardware resources
|
||||||
//
|
//
|
||||||
// Copyright (C) 2007 Lasse Collin
|
// Copyright (C) 2007 Lasse Collin
|
||||||
|
@ -17,12 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef HARDWARE_H
|
|
||||||
#define HARDWARE_H
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
extern size_t opt_threads;
|
extern size_t opt_threads;
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,5 +35,3 @@ extern uint64_t hardware_memlimit_encoder(void);
|
||||||
|
|
||||||
/// Get the memory usage limit for decoding. By default this is 30 % of RAM.
|
/// Get the memory usage limit for decoding. By default this is 30 % of RAM.
|
||||||
extern uint64_t hardware_memlimit_decoder(void);
|
extern uint64_t hardware_memlimit_decoder(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
93
src/xz/io.c
93
src/xz/io.c
|
@ -27,6 +27,38 @@
|
||||||
# include <utime.h>
|
# include <utime.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef O_BINARY
|
||||||
|
# define O_BINARY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef O_NOCTTY
|
||||||
|
# define O_NOCTTY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
# include "open_stdxxx.h"
|
||||||
|
static bool warn_fchown;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
io_init(void)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// If fchown() fails setting the owner, we warn about it only if
|
||||||
|
// we are root.
|
||||||
|
warn_fchown = geteuid() == 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Unlinks a file
|
/// \brief Unlinks a file
|
||||||
///
|
///
|
||||||
|
@ -37,20 +69,22 @@
|
||||||
static void
|
static void
|
||||||
io_unlink(const char *name, const struct stat *known_st)
|
io_unlink(const char *name, const struct stat *known_st)
|
||||||
{
|
{
|
||||||
|
// On Windows, st_ino is meaningless, so don't bother testing it.
|
||||||
|
#ifndef _WIN32
|
||||||
struct stat new_st;
|
struct stat new_st;
|
||||||
|
|
||||||
if (lstat(name, &new_st)
|
if (lstat(name, &new_st)
|
||||||
|| new_st.st_dev != known_st->st_dev
|
|| new_st.st_dev != known_st->st_dev
|
||||||
|| new_st.st_ino != known_st->st_ino) {
|
|| new_st.st_ino != known_st->st_ino)
|
||||||
message_error(_("%s: File seems to be moved, not removing"),
|
message_error(_("%s: File seems to be moved, not removing"),
|
||||||
name);
|
name);
|
||||||
} else {
|
else
|
||||||
|
#endif
|
||||||
// There's a race condition between lstat() and unlink()
|
// There's a race condition between lstat() and unlink()
|
||||||
// but at least we have tried to avoid removing wrong file.
|
// but at least we have tried to avoid removing wrong file.
|
||||||
if (unlink(name))
|
if (unlink(name))
|
||||||
message_error(_("%s: Cannot remove: %s"),
|
message_error(_("%s: Cannot remove: %s"),
|
||||||
name, strerror(errno));
|
name, strerror(errno));
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -63,31 +97,19 @@ io_unlink(const char *name, const struct stat *known_st)
|
||||||
static void
|
static void
|
||||||
io_copy_attrs(const file_pair *pair)
|
io_copy_attrs(const file_pair *pair)
|
||||||
{
|
{
|
||||||
|
// Skip chown and chmod on Windows.
|
||||||
|
#ifndef _WIN32
|
||||||
// This function is more tricky than you may think at first.
|
// This function is more tricky than you may think at first.
|
||||||
// Blindly copying permissions may permit users to access the
|
// Blindly copying permissions may permit users to access the
|
||||||
// destination file who didn't have permission to access the
|
// destination file who didn't have permission to access the
|
||||||
// source file.
|
// source file.
|
||||||
|
|
||||||
// Simple cache to avoid repeated calls to geteuid().
|
|
||||||
static enum {
|
|
||||||
WARN_FCHOWN_UNKNOWN,
|
|
||||||
WARN_FCHOWN_NO,
|
|
||||||
WARN_FCHOWN_YES,
|
|
||||||
} warn_fchown = WARN_FCHOWN_UNKNOWN;
|
|
||||||
|
|
||||||
// Try changing the owner of the file. If we aren't root or the owner
|
// Try changing the owner of the file. If we aren't root or the owner
|
||||||
// isn't already us, fchown() probably doesn't succeed. We warn
|
// isn't already us, fchown() probably doesn't succeed. We warn
|
||||||
// about failing fchown() only if we are root.
|
// about failing fchown() only if we are root.
|
||||||
if (fchown(pair->dest_fd, pair->src_st.st_uid, -1)
|
if (fchown(pair->dest_fd, pair->src_st.st_uid, -1) && warn_fchown)
|
||||||
&& warn_fchown != WARN_FCHOWN_NO) {
|
message_warning(_("%s: Cannot set the file owner: %s"),
|
||||||
if (warn_fchown == WARN_FCHOWN_UNKNOWN)
|
pair->dest_name, strerror(errno));
|
||||||
warn_fchown = geteuid() == 0
|
|
||||||
? WARN_FCHOWN_YES : WARN_FCHOWN_NO;
|
|
||||||
|
|
||||||
if (warn_fchown == WARN_FCHOWN_YES)
|
|
||||||
message_warning(_("%s: Cannot set the file owner: %s"),
|
|
||||||
pair->dest_name, strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
|
|
||||||
|
@ -113,6 +135,7 @@ io_copy_attrs(const file_pair *pair)
|
||||||
if (fchmod(pair->dest_fd, mode))
|
if (fchmod(pair->dest_fd, mode))
|
||||||
message_warning(_("%s: Cannot set the file permissions: %s"),
|
message_warning(_("%s: Cannot set the file permissions: %s"),
|
||||||
pair->dest_name, strerror(errno));
|
pair->dest_name, strerror(errno));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copy the timestamps. We have several possible ways to do this, of
|
// Copy the timestamps. We have several possible ways to do this, of
|
||||||
// which some are better in both security and precision.
|
// which some are better in both security and precision.
|
||||||
|
@ -210,6 +233,9 @@ io_open_src(file_pair *pair)
|
||||||
// There's nothing to open when reading from stdin.
|
// There's nothing to open when reading from stdin.
|
||||||
if (pair->src_name == stdin_filename) {
|
if (pair->src_name == stdin_filename) {
|
||||||
pair->src_fd = STDIN_FILENO;
|
pair->src_fd = STDIN_FILENO;
|
||||||
|
#ifdef _WIN32
|
||||||
|
setmode(STDIN_FILENO, O_BINARY);
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +244,9 @@ io_open_src(file_pair *pair)
|
||||||
const bool reg_files_only = !opt_stdout && !opt_force;
|
const bool reg_files_only = !opt_stdout && !opt_force;
|
||||||
|
|
||||||
// Flags for open()
|
// Flags for open()
|
||||||
int flags = O_RDONLY | O_NOCTTY;
|
int flags = O_RDONLY | O_BINARY | O_NOCTTY;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
// If we accept only regular files, we need to be careful to avoid
|
// If we accept only regular files, we need to be careful to avoid
|
||||||
// problems with special files like devices and FIFOs. O_NONBLOCK
|
// problems with special files like devices and FIFOs. O_NONBLOCK
|
||||||
// prevents blocking when opening such files. When we want to accept
|
// prevents blocking when opening such files. When we want to accept
|
||||||
|
@ -227,11 +254,12 @@ io_open_src(file_pair *pair)
|
||||||
// block waiting e.g. FIFOs to become readable.
|
// block waiting e.g. FIFOs to become readable.
|
||||||
if (reg_files_only)
|
if (reg_files_only)
|
||||||
flags |= O_NONBLOCK;
|
flags |= O_NONBLOCK;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef O_NOFOLLOW
|
#if defined(O_NOFOLLOW)
|
||||||
if (reg_files_only)
|
if (reg_files_only)
|
||||||
flags |= O_NOFOLLOW;
|
flags |= O_NOFOLLOW;
|
||||||
#else
|
#elif !defined(_WIN32)
|
||||||
// Some POSIX-like systems lack O_NOFOLLOW (it's not required
|
// Some POSIX-like systems lack O_NOFOLLOW (it's not required
|
||||||
// by POSIX). Check for symlinks with a separate lstat() on
|
// by POSIX). Check for symlinks with a separate lstat() on
|
||||||
// these systems.
|
// these systems.
|
||||||
|
@ -335,6 +363,7 @@ io_open_src(file_pair *pair)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
// Drop O_NONBLOCK, which is used only when we are accepting only
|
// Drop O_NONBLOCK, which is used only when we are accepting only
|
||||||
// regular files. After the open() call, we want things to block
|
// regular files. After the open() call, we want things to block
|
||||||
// instead of giving EAGAIN.
|
// instead of giving EAGAIN.
|
||||||
|
@ -348,6 +377,7 @@ io_open_src(file_pair *pair)
|
||||||
if (fcntl(pair->src_fd, F_SETFL, flags))
|
if (fcntl(pair->src_fd, F_SETFL, flags))
|
||||||
goto error_msg;
|
goto error_msg;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Stat the source file. We need the result also when we copy
|
// Stat the source file. We need the result also when we copy
|
||||||
// the permissions, and when unlinking.
|
// the permissions, and when unlinking.
|
||||||
|
@ -367,6 +397,8 @@ io_open_src(file_pair *pair)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These are meaningless on Windows.
|
||||||
|
#ifndef _WIN32
|
||||||
if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
|
if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
|
||||||
// gzip rejects setuid and setgid files even
|
// gzip rejects setuid and setgid files even
|
||||||
// when --force was used. bzip2 doesn't check
|
// when --force was used. bzip2 doesn't check
|
||||||
|
@ -396,6 +428,7 @@ io_open_src(file_pair *pair)
|
||||||
"skipping"), pair->src_name);
|
"skipping"), pair->src_name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -417,14 +450,23 @@ static void
|
||||||
io_close_src(file_pair *pair, bool success)
|
io_close_src(file_pair *pair, bool success)
|
||||||
{
|
{
|
||||||
if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
|
if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
(void)close(pair->src_fd);
|
||||||
|
#endif
|
||||||
|
|
||||||
// If we are going to unlink(), do it before closing the file.
|
// If we are going to unlink(), do it before closing the file.
|
||||||
// This way there's no risk that someone replaces the file and
|
// This way there's no risk that someone replaces the file and
|
||||||
// happens to get same inode number, which would make us
|
// happens to get same inode number, which would make us
|
||||||
// unlink() wrong file.
|
// unlink() wrong file.
|
||||||
|
//
|
||||||
|
// NOTE: Windows is an exception to this, because it doesn't
|
||||||
|
// allow unlinking files that are open. *sigh*
|
||||||
if (success && !opt_keep_original)
|
if (success && !opt_keep_original)
|
||||||
io_unlink(pair->src_name, &pair->src_st);
|
io_unlink(pair->src_name, &pair->src_st);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
(void)close(pair->src_fd);
|
(void)close(pair->src_fd);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -438,6 +480,9 @@ io_open_dest(file_pair *pair)
|
||||||
// We don't modify or free() this.
|
// We don't modify or free() this.
|
||||||
pair->dest_name = (char *)"(stdout)";
|
pair->dest_name = (char *)"(stdout)";
|
||||||
pair->dest_fd = STDOUT_FILENO;
|
pair->dest_fd = STDOUT_FILENO;
|
||||||
|
#ifdef _WIN32
|
||||||
|
setmode(STDOUT_FILENO, O_BINARY);
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,7 +506,7 @@ io_open_dest(file_pair *pair)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the file.
|
// Open the file.
|
||||||
const int flags = O_WRONLY | O_NOCTTY | O_CREAT | O_EXCL;
|
const int flags = O_WRONLY | O_BINARY | O_NOCTTY | O_CREAT | O_EXCL;
|
||||||
const mode_t mode = S_IRUSR | S_IWUSR;
|
const mode_t mode = S_IRUSR | S_IWUSR;
|
||||||
pair->dest_fd = open(pair->dest_name, flags, mode);
|
pair->dest_fd = open(pair->dest_name, flags, mode);
|
||||||
|
|
||||||
|
|
12
src/xz/io.h
12
src/xz/io.h
|
@ -17,12 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef IO_H
|
|
||||||
#define IO_H
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Some systems have suboptimal BUFSIZ. Use a bit bigger value on them.
|
// Some systems have suboptimal BUFSIZ. Use a bit bigger value on them.
|
||||||
#if BUFSIZ <= 1024
|
#if BUFSIZ <= 1024
|
||||||
# define IO_BUFFER_SIZE 8192
|
# define IO_BUFFER_SIZE 8192
|
||||||
|
@ -58,6 +52,10 @@ typedef struct {
|
||||||
} file_pair;
|
} file_pair;
|
||||||
|
|
||||||
|
|
||||||
|
/// \brief Initialize the I/O module
|
||||||
|
extern void io_init(void);
|
||||||
|
|
||||||
|
|
||||||
/// \brief Opens a file pair
|
/// \brief Opens a file pair
|
||||||
extern file_pair *io_open(const char *src_name);
|
extern file_pair *io_open(const char *src_name);
|
||||||
|
|
||||||
|
@ -93,5 +91,3 @@ extern size_t io_read(file_pair *pair, uint8_t *buf, size_t size);
|
||||||
/// \return On success, zero is returned. On error, -1 is returned
|
/// \return On success, zero is returned. On error, -1 is returned
|
||||||
/// and error message printed.
|
/// and error message printed.
|
||||||
extern bool io_write(const file_pair *pair, const uint8_t *buf, size_t size);
|
extern bool io_write(const file_pair *pair, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
132
src/xz/main.c
132
src/xz/main.c
|
@ -18,119 +18,12 @@
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
#include "open_stdxxx.h"
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
volatile sig_atomic_t user_abort = false;
|
|
||||||
|
|
||||||
/// Exit status to use. This can be changed with set_exit_status().
|
/// Exit status to use. This can be changed with set_exit_status().
|
||||||
static enum exit_status_type exit_status = E_SUCCESS;
|
static enum exit_status_type exit_status = E_SUCCESS;
|
||||||
|
|
||||||
/// If we were interrupted by a signal, we store the signal number so that
|
|
||||||
/// we can raise that signal to kill the program when all cleanups have
|
|
||||||
/// been done.
|
|
||||||
static volatile sig_atomic_t exit_signal = 0;
|
|
||||||
|
|
||||||
/// Mask of signals for which have have established a signal handler to set
|
|
||||||
/// user_abort to true.
|
|
||||||
static sigset_t hooked_signals;
|
|
||||||
|
|
||||||
/// signals_block() and signals_unblock() can be called recursively.
|
|
||||||
static size_t signals_block_count = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
signal_handler(int sig)
|
|
||||||
{
|
|
||||||
exit_signal = sig;
|
|
||||||
user_abort = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
establish_signal_handlers(void)
|
|
||||||
{
|
|
||||||
// List of signals for which we establish the signal handler.
|
|
||||||
static const int sigs[] = {
|
|
||||||
SIGINT,
|
|
||||||
SIGTERM,
|
|
||||||
#ifdef SIGHUP
|
|
||||||
SIGHUP,
|
|
||||||
#endif
|
|
||||||
#ifdef SIGPIPE
|
|
||||||
SIGPIPE,
|
|
||||||
#endif
|
|
||||||
#ifdef SIGXCPU
|
|
||||||
SIGXCPU,
|
|
||||||
#endif
|
|
||||||
#ifdef SIGXFSZ
|
|
||||||
SIGXFSZ,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// Mask of the signals for which we have established a signal handler.
|
|
||||||
sigemptyset(&hooked_signals);
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i)
|
|
||||||
sigaddset(&hooked_signals, sigs[i]);
|
|
||||||
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
// All the signals that we handle we also blocked while the signal
|
|
||||||
// handler runs.
|
|
||||||
sa.sa_mask = hooked_signals;
|
|
||||||
|
|
||||||
// Don't set SA_RESTART, because we want EINTR so that we can check
|
|
||||||
// for user_abort and cleanup before exiting. We block the signals
|
|
||||||
// for which we have established a handler when we don't want EINTR.
|
|
||||||
sa.sa_flags = 0;
|
|
||||||
sa.sa_handler = &signal_handler;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i) {
|
|
||||||
// If the parent process has left some signals ignored,
|
|
||||||
// we don't unignore them.
|
|
||||||
struct sigaction old;
|
|
||||||
if (sigaction(sigs[i], NULL, &old) == 0
|
|
||||||
&& old.sa_handler == SIG_IGN)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Establish the signal handler.
|
|
||||||
if (sigaction(sigs[i], &sa, NULL))
|
|
||||||
message_signal_handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
|
||||||
signals_block(void)
|
|
||||||
{
|
|
||||||
if (signals_block_count++ == 0) {
|
|
||||||
const int saved_errno = errno;
|
|
||||||
mythread_sigmask(SIG_BLOCK, &hooked_signals, NULL);
|
|
||||||
errno = saved_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
|
||||||
signals_unblock(void)
|
|
||||||
{
|
|
||||||
assert(signals_block_count > 0);
|
|
||||||
|
|
||||||
if (--signals_block_count == 0) {
|
|
||||||
const int saved_errno = errno;
|
|
||||||
mythread_sigmask(SIG_UNBLOCK, &hooked_signals, NULL);
|
|
||||||
errno = saved_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
set_exit_status(enum exit_status_type new_status)
|
set_exit_status(enum exit_status_type new_status)
|
||||||
|
@ -174,19 +67,8 @@ my_exit(enum exit_status_type status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have got a signal, raise it to kill the program.
|
// If we have got a signal, raise it to kill the program.
|
||||||
const int sig = exit_signal;
|
// Otherwise we just call exit().
|
||||||
if (sig != 0) {
|
signals_exit();
|
||||||
struct sigaction sa;
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
sigfillset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = 0;
|
|
||||||
sigaction(sig, &sa, NULL);
|
|
||||||
raise(exit_signal);
|
|
||||||
|
|
||||||
// If, for some weird reason, the signal doesn't kill us,
|
|
||||||
// we safely fall to the exit below.
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,11 +160,9 @@ read_name(const args_info *args)
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
// Make sure that stdin, stdout, and and stderr are connected to
|
// Initialize the file I/O as the very first step. This makes sure
|
||||||
// a valid file descriptor. Exit immediatelly with exit code ERROR
|
// that stdin, stdout, and stderr are something valid.
|
||||||
// if we cannot make the file descriptors valid. Maybe we should
|
io_init();
|
||||||
// print an error message, but our stderr could be screwed anyway.
|
|
||||||
open_stdxxx(E_ERROR);
|
|
||||||
|
|
||||||
// Set up the locale.
|
// Set up the locale.
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
@ -334,7 +214,7 @@ main(int argc, char **argv)
|
||||||
// Hook the signal handlers. We don't need these before we start
|
// Hook the signal handlers. We don't need these before we start
|
||||||
// the actual action, so this is done after parsing the command
|
// the actual action, so this is done after parsing the command
|
||||||
// line arguments.
|
// line arguments.
|
||||||
establish_signal_handlers();
|
signals_init();
|
||||||
|
|
||||||
// Process the files given on the command line. Note that if no names
|
// Process the files given on the command line. Note that if no names
|
||||||
// were given, parse_args() gave us a fake "-" filename.
|
// were given, parse_args() gave us a fake "-" filename.
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef MAIN_H
|
|
||||||
#define MAIN_H
|
|
||||||
|
|
||||||
/// Possible exit status values. These are the same as used by gzip and bzip2.
|
/// Possible exit status values. These are the same as used by gzip and bzip2.
|
||||||
enum exit_status_type {
|
enum exit_status_type {
|
||||||
E_SUCCESS = 0,
|
E_SUCCESS = 0,
|
||||||
|
@ -28,22 +25,6 @@ enum exit_status_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// If this is true, we will clean up the possibly incomplete output file,
|
|
||||||
/// return to main() as soon as practical. That is, the code needs to poll
|
|
||||||
/// this variable in various places.
|
|
||||||
extern volatile sig_atomic_t user_abort;
|
|
||||||
|
|
||||||
|
|
||||||
/// 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.
|
|
||||||
extern void signals_block(void);
|
|
||||||
|
|
||||||
|
|
||||||
/// Unblock the signals blocked by signals_block().
|
|
||||||
extern void signals_unblock(void);
|
|
||||||
|
|
||||||
|
|
||||||
/// Sets the exit status after a warning or error has occurred. If new_status
|
/// Sets the exit status after a warning or error has occurred. If new_status
|
||||||
/// is EX_WARNING and the old exit status was already EX_ERROR, the exit
|
/// is EX_WARNING and the old exit status was already EX_ERROR, the exit
|
||||||
/// status is not changed.
|
/// status is not changed.
|
||||||
|
@ -55,6 +36,3 @@ extern void set_exit_status(enum exit_status_type new_status);
|
||||||
/// a signal, this function will raise it so that to the parent process it
|
/// 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.
|
/// appears that we were killed by the signal sent by the user.
|
||||||
extern void my_exit(enum exit_status_type status) lzma_attribute((noreturn));
|
extern void my_exit(enum exit_status_type status) lzma_attribute((noreturn));
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -19,10 +19,15 @@
|
||||||
|
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
#if defined(HAVE_SYS_TIME_H)
|
#ifdef HAVE_SYS_TIME_H
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#elif defined(SIGALRM)
|
#endif
|
||||||
// FIXME
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# ifndef _WIN32_WINNT
|
||||||
|
# define _WIN32_WINNT 0x0500
|
||||||
|
# endif
|
||||||
|
# include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -76,6 +81,47 @@ static double start_time;
|
||||||
static volatile sig_atomic_t progress_needs_updating = false;
|
static volatile sig_atomic_t progress_needs_updating = false;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
static HANDLE timer_queue = NULL;
|
||||||
|
static HANDLE timer_timer = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void CALLBACK
|
||||||
|
timer_callback(PVOID dummy1 lzma_attribute((unused)),
|
||||||
|
BOOLEAN dummy2 lzma_attribute((unused)))
|
||||||
|
{
|
||||||
|
progress_needs_updating = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Emulate alarm() on Windows.
|
||||||
|
static void
|
||||||
|
my_alarm(unsigned int seconds)
|
||||||
|
{
|
||||||
|
// Just in case creating the queue has failed.
|
||||||
|
if (timer_queue == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If an old timer_timer exists, get rid of it first.
|
||||||
|
if (timer_timer != NULL) {
|
||||||
|
(void)DeleteTimerQueueTimer(timer_queue, timer_timer, NULL);
|
||||||
|
timer_timer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it fails, tough luck. It's not that important.
|
||||||
|
(void)CreateTimerQueueTimer(&timer_timer, timer_queue, &timer_callback,
|
||||||
|
NULL, 1000U * seconds, 0,
|
||||||
|
WT_EXECUTEINTIMERTHREAD | WT_EXECUTEONLYONCE);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define my_alarm alarm
|
||||||
|
|
||||||
/// Signal handler for SIGALRM
|
/// Signal handler for SIGALRM
|
||||||
static void
|
static void
|
||||||
progress_signal_handler(int sig lzma_attribute((unused)))
|
progress_signal_handler(int sig lzma_attribute((unused)))
|
||||||
|
@ -84,6 +130,7 @@ progress_signal_handler(int sig lzma_attribute((unused)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Get the current time as double
|
/// Get the current time as double
|
||||||
static double
|
static double
|
||||||
|
@ -157,7 +204,9 @@ message_init(const char *given_argv0)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SIGALRM
|
#ifdef _WIN32
|
||||||
|
timer_queue = CreateTimerQueue();
|
||||||
|
#else
|
||||||
// Establish the signal handler for SIGALRM. Since this signal
|
// Establish the signal handler for SIGALRM. Since this signal
|
||||||
// doesn't require any quick action, we set SA_RESTART.
|
// doesn't require any quick action, we set SA_RESTART.
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
@ -266,7 +315,7 @@ message_progress_start(const char *src_name, uint64_t in_size)
|
||||||
// progress_needs_updating to true here immediatelly, but
|
// progress_needs_updating to true here immediatelly, but
|
||||||
// setting the timer looks better to me, since extremely
|
// setting the timer looks better to me, since extremely
|
||||||
// early progress info is pretty much useless.
|
// early progress info is pretty much useless.
|
||||||
alarm(1);
|
my_alarm(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -486,7 +535,7 @@ message_progress_update(uint64_t in_pos, uint64_t out_pos)
|
||||||
// Updating the progress info was finished. Reset
|
// Updating the progress info was finished. Reset
|
||||||
// progress_needs_updating to wait for the next SIGALRM.
|
// progress_needs_updating to wait for the next SIGALRM.
|
||||||
//
|
//
|
||||||
// NOTE: This has to be done before alarm() call or with (very) bad
|
// NOTE: This has to be done before my_alarm() call or with (very) bad
|
||||||
// luck we could be setting this to false after the alarm has already
|
// luck we could be setting this to false after the alarm has already
|
||||||
// been triggered.
|
// been triggered.
|
||||||
progress_needs_updating = false;
|
progress_needs_updating = false;
|
||||||
|
@ -498,7 +547,7 @@ message_progress_update(uint64_t in_pos, uint64_t out_pos)
|
||||||
|
|
||||||
// Restart the timer so that progress_needs_updating gets
|
// Restart the timer so that progress_needs_updating gets
|
||||||
// set to true after about one second.
|
// set to true after about one second.
|
||||||
alarm(1);
|
my_alarm(1);
|
||||||
} else {
|
} else {
|
||||||
// The progress message was printed because user had sent us
|
// The progress message was printed because user had sent us
|
||||||
// SIGALRM. In this case, each progress message is printed
|
// SIGALRM. In this case, each progress message is printed
|
||||||
|
@ -521,7 +570,7 @@ message_progress_end(uint64_t in_pos, uint64_t out_pos, bool success)
|
||||||
|
|
||||||
// Cancel a pending alarm, if any.
|
// Cancel a pending alarm, if any.
|
||||||
if (progress_automatic) {
|
if (progress_automatic) {
|
||||||
alarm(0);
|
my_alarm(0);
|
||||||
progress_active = false;
|
progress_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef MESSAGE_H
|
|
||||||
#define MESSAGE_H
|
|
||||||
|
|
||||||
|
|
||||||
/// Verbosity levels
|
/// Verbosity levels
|
||||||
enum message_verbosity {
|
enum message_verbosity {
|
||||||
V_SILENT, ///< No messages
|
V_SILENT, ///< No messages
|
||||||
|
@ -133,5 +129,3 @@ extern void message_progress_update(uint64_t in_pos, uint64_t out_pos);
|
||||||
///
|
///
|
||||||
extern void message_progress_end(
|
extern void message_progress_end(
|
||||||
uint64_t in_pos, uint64_t out_pos, bool success);
|
uint64_t in_pos, uint64_t out_pos, bool success);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -17,12 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef OPTIONS_H
|
|
||||||
#define OPTIONS_H
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
/// \brief Parser for Subblock options
|
/// \brief Parser for Subblock options
|
||||||
///
|
///
|
||||||
/// \return Pointer to allocated options structure.
|
/// \return Pointer to allocated options structure.
|
||||||
|
@ -42,5 +36,3 @@ extern lzma_options_delta *options_delta(const char *str);
|
||||||
/// \return Pointer to allocated options structure.
|
/// \return Pointer to allocated options structure.
|
||||||
/// Doesn't return on error.
|
/// Doesn't return on error.
|
||||||
extern lzma_options_lzma *options_lzma(const char *str);
|
extern lzma_options_lzma *options_lzma(const char *str);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PRIVATE_H
|
|
||||||
#define PRIVATE_H
|
|
||||||
|
|
||||||
#include "sysdefs.h"
|
#include "sysdefs.h"
|
||||||
#include "mythread.h"
|
#include "mythread.h"
|
||||||
#include "lzma.h"
|
#include "lzma.h"
|
||||||
|
@ -41,6 +38,18 @@
|
||||||
# define N_(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
|
# define N_(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STDIN_FILENO
|
||||||
|
# define STDIN_FILENO (fileno(stdin))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STDOUT_FILENO
|
||||||
|
# define STDOUT_FILENO (fileno(stdout))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef STDERR_FILENO
|
||||||
|
# define STDERR_FILENO (fileno(stderr))
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
|
@ -48,7 +57,6 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
#include "signals.h"
|
||||||
#include "suffix.h"
|
#include "suffix.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
/// \file process.c
|
/// \file process.h
|
||||||
/// \brief Compresses or uncompresses a file
|
/// \brief Compresses or uncompresses a file
|
||||||
//
|
//
|
||||||
// Copyright (C) 2007 Lasse Collin
|
// Copyright (C) 2007 Lasse Collin
|
||||||
|
@ -17,12 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PROCESS_H
|
|
||||||
#define PROCESS_H
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
enum operation_mode {
|
enum operation_mode {
|
||||||
MODE_COMPRESS,
|
MODE_COMPRESS,
|
||||||
MODE_DECOMPRESS,
|
MODE_DECOMPRESS,
|
||||||
|
@ -69,5 +63,3 @@ extern void coder_set_compression_settings(void);
|
||||||
extern void process_init(void);
|
extern void process_init(void);
|
||||||
|
|
||||||
extern void process_file(const char *filename);
|
extern void process_file(const char *filename);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
180
src/xz/signals.c
Normal file
180
src/xz/signals.c
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
/// \file signals.c
|
||||||
|
/// \brief Handling signals to abort operation
|
||||||
|
//
|
||||||
|
// Copyright (C) 2007-2009 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"
|
||||||
|
|
||||||
|
|
||||||
|
volatile sig_atomic_t user_abort = false;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
/// If we were interrupted by a signal, we store the signal number so that
|
||||||
|
/// we can raise that signal to kill the program when all cleanups have
|
||||||
|
/// been done.
|
||||||
|
static volatile sig_atomic_t exit_signal = 0;
|
||||||
|
|
||||||
|
/// Mask of signals for which have have established a signal handler to set
|
||||||
|
/// user_abort to true.
|
||||||
|
static sigset_t hooked_signals;
|
||||||
|
|
||||||
|
/// signals_block() and signals_unblock() can be called recursively.
|
||||||
|
static size_t signals_block_count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler(int sig)
|
||||||
|
{
|
||||||
|
exit_signal = sig;
|
||||||
|
user_abort = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
signals_init(void)
|
||||||
|
{
|
||||||
|
// List of signals for which we establish the signal handler.
|
||||||
|
static const int sigs[] = {
|
||||||
|
SIGINT,
|
||||||
|
SIGTERM,
|
||||||
|
#ifdef SIGHUP
|
||||||
|
SIGHUP,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
SIGPIPE,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXCPU
|
||||||
|
SIGXCPU,
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXFSZ
|
||||||
|
SIGXFSZ,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mask of the signals for which we have established a signal handler.
|
||||||
|
sigemptyset(&hooked_signals);
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i)
|
||||||
|
sigaddset(&hooked_signals, sigs[i]);
|
||||||
|
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
// All the signals that we handle we also blocked while the signal
|
||||||
|
// handler runs.
|
||||||
|
sa.sa_mask = hooked_signals;
|
||||||
|
|
||||||
|
// Don't set SA_RESTART, because we want EINTR so that we can check
|
||||||
|
// for user_abort and cleanup before exiting. We block the signals
|
||||||
|
// for which we have established a handler when we don't want EINTR.
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sa.sa_handler = &signal_handler;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i) {
|
||||||
|
// If the parent process has left some signals ignored,
|
||||||
|
// we don't unignore them.
|
||||||
|
struct sigaction old;
|
||||||
|
if (sigaction(sigs[i], NULL, &old) == 0
|
||||||
|
&& old.sa_handler == SIG_IGN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Establish the signal handler.
|
||||||
|
if (sigaction(sigs[i], &sa, NULL))
|
||||||
|
message_signal_handler();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
signals_block(void)
|
||||||
|
{
|
||||||
|
if (signals_block_count++ == 0) {
|
||||||
|
const int saved_errno = errno;
|
||||||
|
mythread_sigmask(SIG_BLOCK, &hooked_signals, NULL);
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
signals_unblock(void)
|
||||||
|
{
|
||||||
|
assert(signals_block_count > 0);
|
||||||
|
|
||||||
|
if (--signals_block_count == 0) {
|
||||||
|
const int saved_errno = errno;
|
||||||
|
mythread_sigmask(SIG_UNBLOCK, &hooked_signals, NULL);
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
signals_exit(void)
|
||||||
|
{
|
||||||
|
const int sig = exit_signal;
|
||||||
|
|
||||||
|
if (sig != 0) {
|
||||||
|
struct sigaction sa;
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigfillset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sigaction(sig, &sa, NULL);
|
||||||
|
raise(exit_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// While Windows has some very basic signal handling functions as required
|
||||||
|
// by C89, they are not really used, or so I understood. Instead, we use
|
||||||
|
// SetConsoleCtrlHandler() to catch user pressing C-c.
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL WINAPI
|
||||||
|
signal_handler(DWORD type lzma_attribute((unused)))
|
||||||
|
{
|
||||||
|
// Since we don't get a signal number which we could raise() at
|
||||||
|
// signals_exit() like on POSIX, just set the exit status to
|
||||||
|
// indicate an error, so that we cannot return with zero exit status.
|
||||||
|
set_exit_status(E_ERROR);
|
||||||
|
user_abort = true;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern void
|
||||||
|
signals_init(void)
|
||||||
|
{
|
||||||
|
if (!SetConsoleCtrlHandler(&signal_handler, TRUE))
|
||||||
|
message_signal_handler();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
51
src/xz/signals.h
Normal file
51
src/xz/signals.h
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
/// \file signals.h
|
||||||
|
/// \brief Handling signals to abort operation
|
||||||
|
//
|
||||||
|
// Copyright (C) 2007-2009 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.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// If this is true, we will clean up the possibly incomplete output file,
|
||||||
|
/// return to main() as soon as practical. That is, the code needs to poll
|
||||||
|
/// this variable in various places.
|
||||||
|
extern volatile sig_atomic_t user_abort;
|
||||||
|
|
||||||
|
|
||||||
|
/// Initialize the signal handler, which will set user_abort to true when
|
||||||
|
/// user e.g. presses C-c.
|
||||||
|
extern void signals_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
extern void signals_block(void);
|
||||||
|
|
||||||
|
/// Unblock the signals blocked by signals_block().
|
||||||
|
extern void signals_unblock(void);
|
||||||
|
|
||||||
|
/// 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
|
|
@ -17,9 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef SUFFIX_H
|
|
||||||
#define SUFFIX_H
|
|
||||||
|
|
||||||
/// \brief Get the name of the destination file
|
/// \brief Get the name of the destination file
|
||||||
///
|
///
|
||||||
/// Depending on the global variable opt_mode, this tries to find a matching
|
/// Depending on the global variable opt_mode, this tries to find a matching
|
||||||
|
@ -36,5 +33,3 @@ extern char *suffix_get_dest_name(const char *src_name);
|
||||||
/// suffix, thus if this is called multiple times, the old suffixes are freed
|
/// suffix, thus if this is called multiple times, the old suffixes are freed
|
||||||
/// and forgotten.
|
/// and forgotten.
|
||||||
extern void suffix_set(const char *suffix);
|
extern void suffix_set(const char *suffix);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -116,9 +116,8 @@ str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
message_fatal(_("Value of the option `%s' must be in the range "
|
message_fatal(_("Value of the option `%s' must be in the range "
|
||||||
"[%llu, %llu]"), name,
|
"[%" PRIu64 ", %" PRIu64 "]"),
|
||||||
(unsigned long long)(min),
|
name, min, max);
|
||||||
(unsigned long long)(max));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef UTIL_H
|
|
||||||
#define UTIL_H
|
|
||||||
|
|
||||||
/// \brief Safe malloc() that never returns NULL
|
/// \brief Safe malloc() that never returns NULL
|
||||||
///
|
///
|
||||||
/// \note xmalloc(), xrealloc(), and xstrdup() must not be used when
|
/// \note xmalloc(), xrealloc(), and xstrdup() must not be used when
|
||||||
|
@ -67,5 +64,3 @@ extern bool is_tty_stdin(void);
|
||||||
/// If stdout is a terminal, an error message is printed and exit status set
|
/// If stdout is a terminal, an error message is printed and exit status set
|
||||||
/// to EXIT_ERROR.
|
/// to EXIT_ERROR.
|
||||||
extern bool is_tty_stdout(void);
|
extern bool is_tty_stdout(void);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in a new issue