diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | include/mscp.h | 18 | ||||
-rw-r--r-- | src/atomic.h | 2 | ||||
-rw-r--r-- | src/fileops.c | 6 | ||||
-rw-r--r-- | src/main.c | 36 | ||||
-rw-r--r-- | src/message.c | 50 | ||||
-rw-r--r-- | src/message.h | 57 | ||||
-rw-r--r-- | src/minmax.h | 8 | ||||
-rw-r--r-- | src/mscp.c | 88 | ||||
-rw-r--r-- | src/path.c | 67 | ||||
-rw-r--r-- | src/path.h | 1 | ||||
-rw-r--r-- | src/platform.c | 12 | ||||
-rw-r--r-- | src/print.c | 19 | ||||
-rw-r--r-- | src/print.h | 35 | ||||
-rw-r--r-- | src/ssh.c | 45 | ||||
-rw-r--r-- | src/strerrno.c | 41 | ||||
-rw-r--r-- | src/strerrno.h | 33 | ||||
-rw-r--r-- | src/util.h | 39 |
18 files changed, 268 insertions, 292 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b651e48..600cfd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,7 +98,8 @@ list(APPEND MSCP_BUILD_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/include) # libmscp.a set(LIBMSCP_SRC - src/mscp.c src/ssh.c src/fileops.c src/path.c src/platform.c src/message.c + src/mscp.c src/ssh.c src/fileops.c src/path.c src/platform.c + src/print.c src/strerrno.c ${OPENBSD_COMPAT_SRC}) add_library(mscp-static STATIC ${LIBMSCP_SRC}) target_include_directories(mscp-static diff --git a/include/mscp.h b/include/mscp.h index 1c3528c..3fafd7b 100644 --- a/include/mscp.h +++ b/include/mscp.h @@ -120,7 +120,6 @@ struct mscp *mscp_init(const char *remote_host, int direction, * @param m mscp instance. * * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_connect(struct mscp *m); @@ -136,7 +135,6 @@ int mscp_connect(struct mscp *m); * @param src_path source file path to be copied. * * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_add_src_path(struct mscp *m, const char *src_path); @@ -150,7 +148,6 @@ int mscp_add_src_path(struct mscp *m, const char *src_path); * @param dst_path destination path to which source files copied. * * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_set_dst_path(struct mscp *m, const char *dst_path); @@ -165,7 +162,6 @@ int mscp_set_dst_path(struct mscp *m, const char *dst_path); * @param m mscp instance. * * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_scan(struct mscp *m); @@ -176,7 +172,6 @@ int mscp_scan(struct mscp *m); * * @param m mscp instance. * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_scan_join(struct mscp *m); @@ -189,7 +184,6 @@ int mscp_scan_join(struct mscp *m); * @param m mscp instance. * * @return number of threads on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. * * @see mscp_join() */ @@ -211,7 +205,6 @@ void mscp_stop(struct mscp *m); * @param m mscp instance. * * @return 0 on success, < 0 if an error occured. - * mscp_get_error() can be used to retrieve error message. */ int mscp_join(struct mscp *m); @@ -261,15 +254,4 @@ enum { }; - -/** - * @brief Get the recent error message from libmscp. Note that this - * function is not thread-safe. - * - * @return pointer to the message. - */ -const char *mscp_get_error(void); - - - #endif /* _MSCP_H_ */ diff --git a/src/atomic.h b/src/atomic.h index fc00788..33d39d9 100644 --- a/src/atomic.h +++ b/src/atomic.h @@ -6,8 +6,6 @@ #include <assert.h> #include <pthread.h> -#include <message.h> - typedef int refcnt; static inline void refcnt_inc(refcnt *cnt) diff --git a/src/fileops.c b/src/fileops.c index 5dbbebd..f24b088 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -9,7 +9,7 @@ #include <fileops.h> #include <ssh.h> -#include <message.h> +#include <print.h> #include <platform.h> @@ -63,7 +63,7 @@ static void sftp_err_to_errno(sftp_session sftp) errno = ENODEV; break; default: - mpr_warn("unkown SSH_FX response %d", sftperr); + pr_warn("unkown SSH_FX response %d", sftperr); } } @@ -199,7 +199,7 @@ static void sftp_attr_to_stat(sftp_attributes attr, struct stat *st) st->st_mode |= S_IFIFO; /* really? */ break; default: - mpr_warn("unkown SSH_FILEXFER_TYPE %d", attr->type); + pr_warn("unkown SSH_FILEXFER_TYPE %d", attr->type); } } @@ -12,7 +12,10 @@ #include <pthread.h> #include <mscp.h> -#include <util.h> +#include <minmax.h> +#include <strerrno.h> +#include <print.h> + #include "config.h" @@ -79,7 +82,7 @@ char *split_user_host_path(const char *s, char **userp, char **hostp, char **pat bool inbrackets = false; if (!(tmp = strdup(s))) { - fprintf(stderr, "stdrup: %s\n", strerror(errno)); + pr_err("stdrup: %s", strerror(errno)); return NULL; } @@ -174,7 +177,7 @@ struct target *validate_targets(char **arg, int len) int n; if ((t = calloc(len, sizeof(struct target))) == NULL) { - fprintf(stderr, "calloc: %s\n", strerror(errno)); + pr_err("calloc: %s", strerrno()); return NULL; } memset(t, 0, len * sizeof(struct target)); @@ -198,19 +201,19 @@ struct target *validate_targets(char **arg, int len) /* check inconsistent remote position in args */ if (t[0].host == NULL && t[len - 1].host == NULL) { - fprintf(stderr, "no remote host given\n"); + pr_err("no remote host given"); goto free_split_out; } if (t[0].host != NULL && t[len - 1].host != NULL) { - fprintf(stderr, "no local path given\n"); + pr_err("no local path given"); goto free_split_out; } return t; invalid_remotes: - fprintf(stderr, "invalid remote host notation\n"); + pr_err("invalid remote host notation"); free_split_out: for (n = 0; n < len; n++) @@ -263,8 +266,7 @@ int main(int argc, char **argv) case 'n': o.nr_threads = atoi(optarg); if (o.nr_threads < 1) { - fprintf(stderr, "invalid number of connections: %s\n", - optarg); + pr_err( "invalid number of connections: %s", optarg); return 1; } break; @@ -373,29 +375,29 @@ int main(int argc, char **argv) } if ((m = mscp_init(remote, direction, &o, &s)) == NULL) { - fprintf(stderr, "mscp_init: %s\n", mscp_get_error()); + pr_err("mscp_init: %s", priv_get_err()); return -1; } if (mscp_connect(m) < 0) { - fprintf(stderr, "mscp_connect: %s\n", mscp_get_error()); + pr_err("mscp_connect: %s", priv_get_err()); return -1; } for (n = 0; n < i - 1; n++) { if (mscp_add_src_path(m, t[n].path) < 0) { - fprintf(stderr, "mscp_add_src_path: %s\n", mscp_get_error()); + pr_err("mscp_add_src_path: %s", priv_get_err()); return -1; } } if (mscp_set_dst_path(m, t[i - 1].path) < 0) { - fprintf(stderr, "mscp_set_dst_path: %s\n", mscp_get_error()); + pr_err("mscp_set_dst_path: %s", priv_get_err()); return -1; } if (mscp_scan(m) < 0) { - fprintf(stderr, "mscp_scan: %s\n", mscp_get_error()); + pr_err("mscp_scan: %s", priv_get_err()); return -1; } @@ -405,22 +407,22 @@ int main(int argc, char **argv) } if (pthread_create(&tid_stat, NULL, print_stat_thread, NULL) < 0) { - fprintf(stderr, "pthread_create: %s\n", strerror(errno)); + pr_err("pthread_create: %s", strerror(errno)); return -1; } if (signal(SIGINT, sigint_handler) == SIG_ERR) { - fprintf(stderr, "signal: %s\n", strerror(errno)); + pr_err("signal: %s", strerror(errno)); return -1; } ret = mscp_start(m); if (ret < 0) - fprintf(stderr, "mscp_start: %s\n", mscp_get_error()); + pr_err("mscp_start: %s", priv_get_err()); ret = mscp_join(m); if (ret != 0) - fprintf(stderr, "mscp_join: %s\n", mscp_get_error()); + pr_err("mscp_join: %s", priv_get_err()); pthread_cancel(tid_stat); pthread_join(tid_stat, NULL); diff --git a/src/message.c b/src/message.c deleted file mode 100644 index ff79675..0000000 --- a/src/message.c +++ /dev/null @@ -1,50 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-only */ -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <limits.h> -#include <pthread.h> - -#include <util.h> -#include <message.h> - -/* strerror_r wrapper */ -__thread char thread_strerror[128]; - -/* mscp error message buffer */ -#define MSCP_ERRMSG_SIZE (PATH_MAX * 2) - -static char errmsg[MSCP_ERRMSG_SIZE]; - -void _mscp_set_error(const char *fmt, ...) -{ - va_list va; - - memset(errmsg, 0, sizeof(errmsg)); - va_start(va, fmt); - vsnprintf(errmsg, sizeof(errmsg) - 1, fmt, va); - va_end(va); -} - -const char *mscp_get_error() -{ - return errmsg; -} - - -/* message print functions */ - -static int mprint_severity = MSCP_SEVERITY_WARN; - -void mprint_set_severity(int serverity) -{ - if (serverity < 0) - mprint_severity = -1; /* no print */ - mprint_severity = serverity; -} - -int mprint_get_severity() -{ - return mprint_severity; -} - diff --git a/src/message.h b/src/message.h deleted file mode 100644 index a92d760..0000000 --- a/src/message.h +++ /dev/null @@ -1,57 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-only */ -#ifndef _MESSAGE_H_ -#define _MESSAGE_H_ - -#include <libgen.h> -#include <stdio.h> - -#include <mscp.h> - -/* message print. printed messages are passed to application via msg_fd */ -void mprint_set_severity(int severity); -int mprint_get_severity(); - -#define mprint(fp, severity, fmt, ...) \ - do { \ - if (severity <= mprint_get_severity()) { \ - fprintf(fp, "\r\033[K" fmt "\n", ##__VA_ARGS__); \ - fflush(fp); \ - } \ - } while (0) - -#define mpr_err(fmt, ...) \ - mprint(stderr, MSCP_SEVERITY_ERR, fmt, ##__VA_ARGS__) -#define mpr_warn(fmt, ...) \ - mprint(stderr, MSCP_SEVERITY_WARN, fmt, ##__VA_ARGS__) -#define mpr_notice(fmt, ...) \ - mprint(stdout, MSCP_SEVERITY_NOTICE, fmt, ##__VA_ARGS__) -#define mpr_info(fmt, ...) \ - mprint(stdout, MSCP_SEVERITY_INFO, fmt, ##__VA_ARGS__) -#define mpr_debug(fmt, ...) \ - mprint(stdout, MSCP_SEVERITY_DEBUG, fmt, ##__VA_ARGS__) - - -/* errorno wrapper */ -extern __thread char thread_strerror[128]; - -#ifdef _GNU_SOURCE -/* GNU strerror_r */ -#define strerrno() \ - strerror_r(errno, thread_strerror, sizeof(thread_strerror)) -#else -/* this macro assumes that strerror_r never fails. any good way? */ -#define strerrno() \ - (strerror_r(errno, thread_strerror, sizeof(thread_strerror)) \ - ? thread_strerror : thread_strerror) -#endif - - - -/* error message buffer */ -#define mscp_set_error(fmt, ...) \ - _mscp_set_error("%s:%d:%s: " fmt "\0", \ - basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__) - -void _mscp_set_error(const char *fmt, ...); - -#endif /* _MESSAGE_H_ */ diff --git a/src/minmax.h b/src/minmax.h new file mode 100644 index 0000000..5f575f7 --- /dev/null +++ b/src/minmax.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ +#ifndef _MINMAX_H_ +#define _MINMAX_H_ + +#define min(a, b) (((a) > (b)) ? (b) : (a)) +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +#endif /* _MINMAX_H_ */ @@ -7,13 +7,14 @@ #include <sys/time.h> #include <list.h> -#include <util.h> -#include <ssh.h> +#include <minmax.h> +#include <ssh.h> #include <path.h> #include <fileops.h> -#include <atomic.h> +#include <atomic.h> #include <platform.h> -#include <message.h> +#include <print.h> +#include <strerrno.h> #include <mscp.h> #include <openbsd-compat/openbsd-compat.h> @@ -101,7 +102,7 @@ static int expand_coremask(const char *coremask, int **cores, int *nr_cores) core_list = realloc(NULL, sizeof(int) * 64); if (!core_list) { - mscp_set_error("failed to realloc: %s", strerrno()); + priv_set_errv("failed to realloc: %s", strerrno()); return -1; } @@ -111,7 +112,7 @@ static int expand_coremask(const char *coremask, int **cores, int *nr_cores) c[0] = _coremask[n]; v = strtol(c, NULL, 16); if (v == LONG_MIN || v == LONG_MAX) { - mscp_set_error("invalid coremask: %s", coremask); + priv_set_errv("invalid coremask: %s", coremask); return -1; } @@ -123,7 +124,7 @@ static int expand_coremask(const char *coremask, int **cores, int *nr_cores) nr_usable++; core_list = realloc(core_list, sizeof(int) * nr_usable); if (!core_list) { - mscp_set_error("realloc: %s", strerrno()); + priv_set_errv("realloc: %s", strerrno()); return -1; } core_list[nr_usable - 1] = nr_all - 1; @@ -132,7 +133,7 @@ static int expand_coremask(const char *coremask, int **cores, int *nr_cores) } if (nr_usable < 1) { - mscp_set_error("invalid core mask: %s", coremask); + priv_set_errv("invalid core mask: %s", coremask); return -1; } @@ -149,13 +150,13 @@ static int default_nr_threads() static int validate_and_set_defaut_params(struct mscp_opts *o) { if (o->nr_threads < 0) { - mscp_set_error("invalid nr_threads: %d", o->nr_threads); + priv_set_errv("invalid nr_threads: %d", o->nr_threads); return -1; } else if (o->nr_threads == 0) o->nr_threads = default_nr_threads(); if (o->nr_ahead < 0) { - mscp_set_error("invalid nr_ahead: %d", o->nr_ahead); + priv_set_errv("invalid nr_ahead: %d", o->nr_ahead); return -1; } else if (o->nr_ahead == 0) o->nr_ahead = DEFAULT_NR_AHEAD; @@ -165,7 +166,7 @@ static int validate_and_set_defaut_params(struct mscp_opts *o) else { if (o->min_chunk_sz < getpagesize() || o->min_chunk_sz % getpagesize() != 0) { - mscp_set_error("min chunk size must be " + priv_set_errv("min chunk size must be " "larget than and multiple of page size %d: %lu", getpagesize(), o->min_chunk_sz); return -1; @@ -175,12 +176,12 @@ static int validate_and_set_defaut_params(struct mscp_opts *o) if (o->max_chunk_sz) { if (o->max_chunk_sz < getpagesize() || o->max_chunk_sz % getpagesize() != 0) { - mscp_set_error("min chunk size must be larget than and " + priv_set_errv("min chunk size must be larget than and " "multiple of page size %d: %lu", getpagesize(), o->max_chunk_sz); } if (o->min_chunk_sz > o->max_chunk_sz) { - mscp_set_error("smaller max chunk size than " + priv_set_errv("smaller max chunk size than " "min chunk size: %lu < %lu", o->max_chunk_sz, o->min_chunk_sz); return -1; @@ -190,14 +191,14 @@ static int validate_and_set_defaut_params(struct mscp_opts *o) if (o->buf_sz == 0) o->buf_sz = DEFAULT_BUF_SZ; else if (o->buf_sz == 0) { - mscp_set_error("invalid buf size: %lu", o->buf_sz); + priv_set_errv("invalid buf size: %lu", o->buf_sz); return -1; } if (o->max_startups == 0) o->max_startups = DEFAULT_MAX_STARTUPS; else if (o->max_startups < 0) { - mscp_set_error("invalid max_startups: %d", o->max_startups); + priv_set_errv("invalid max_startups: %d", o->max_startups); return -1; } @@ -216,17 +217,17 @@ struct mscp *mscp_init(const char *remote_host, int direction, int n; if (!remote_host) { - mscp_set_error("empty remote host"); + priv_set_errv("empty remote host"); return NULL; } if (!(direction == MSCP_DIRECTION_L2R || direction == MSCP_DIRECTION_R2L)) { - mscp_set_error("invalid copy direction: %d", direction); + priv_set_errv("invalid copy direction: %d", direction); return NULL; } - mprint_set_severity(o->severity); + set_print_severity(o->severity); if (validate_and_set_defaut_params(o) < 0) { return NULL; @@ -234,7 +235,7 @@ struct mscp *mscp_init(const char *remote_host, int direction, m = malloc(sizeof(*m)); if (!m) { - mscp_set_error("failed to allocate memory: %s", strerrno()); + priv_set_errv("failed to allocate memory: %s", strerrno()); return NULL; } @@ -247,13 +248,13 @@ struct mscp *mscp_init(const char *remote_host, int direction, rwlock_init(&m->thread_rwlock); if ((m->sem = sem_create(o->max_startups)) == NULL) { - mscp_set_error("sem_create: %s", strerrno()); + priv_set_errv("sem_create: %s", strerrno()); goto free_out; } m->remote = strdup(remote_host); if (!m->remote) { - mscp_set_error("failed to allocate memory: %s", strerrno()); + priv_set_errv("failed to allocate memory: %s", strerrno()); goto free_out; } m->direction = direction; @@ -267,7 +268,7 @@ struct mscp *mscp_init(const char *remote_host, int direction, snprintf(c, sizeof(c) - 1, " %d", m->cores[n]); strlcat(b, c, sizeof(b)); } - mpr_notice("usable cpu cores:%s", b); + pr_notice("usable cpu cores:%s", b); } m->opts = o; @@ -295,14 +296,14 @@ int mscp_add_src_path(struct mscp *m, const char *src_path) s = malloc(sizeof(*s)); if (!s) { - mscp_set_error("failed to allocate memory: %s", strerrno()); + priv_set_errv("failed to allocate memory: %s", strerrno()); return -1; } memset(s, 0, sizeof(*s)); s->path = strdup(src_path); if (!s->path) { - mscp_set_error("failed to allocate memory: %s", strerrno()); + priv_set_errv("failed to allocate memory: %s", strerrno()); free(s); return -1; } @@ -314,7 +315,7 @@ int mscp_add_src_path(struct mscp *m, const char *src_path) int mscp_set_dst_path(struct mscp *m, const char *dst_path) { if (strlen(dst_path) + 1 >= PATH_MAX) { - mscp_set_error("too long dst path: %s", dst_path); + priv_set_errv("too long dst path: %s", dst_path); return -1; } @@ -388,7 +389,7 @@ void *mscp_scan_thread(void *arg) dst_sftp = NULL; break; default: - mscp_set_error("invalid copy direction: %d", m->direction); + priv_set_errv("invalid copy direction: %d", m->direction); goto err_out; } @@ -410,19 +411,19 @@ void *mscp_scan_thread(void *arg) a.max_chunk_sz = m->opts->max_chunk_sz; a.chunk_align = get_page_mask(); - mpr_info("start to walk source path(s)"); + pr_info("start to walk source path(s)"); /* walk a src_path recusively, and resolve path->dst_path for each src */ list_for_each_entry(s, &m->src_list, list) { memset(&pglob, 0, sizeof(pglob)); if (mscp_glob(s->path, GLOB_NOCHECK, &pglob, src_sftp) < 0) { - mscp_set_error("mscp_glob: %s", strerrno()); + priv_set_errv("mscp_glob: %s", strerrno()); goto err_out; } for (n = 0; n < pglob.gl_pathc; n++) { if (mscp_stat(pglob.gl_pathv[n], &ss, src_sftp) < 0) { - mscp_set_error("stat: %s %s", s->path, strerrno()); + priv_set_errv("stat: %s %s", s->path, strerrno()); goto err_out; } @@ -443,7 +444,7 @@ void *mscp_scan_thread(void *arg) mscp_globfree(&pglob); } - mpr_info("walk source path(s) done"); + pr_info("walk source path(s) done"); chunk_pool_set_filled(&m->cp); m->ret_scan = 0; return NULL; @@ -458,7 +459,7 @@ int mscp_scan(struct mscp *m) { int ret = pthread_create(&m->tid_scan, NULL, mscp_scan_thread, m); if (ret < 0) { - mscp_set_error("pthread_create_error: %d", ret); + priv_set_errv("pthread_create_error: %d", ret); m->tid_scan = 0; mscp_stop(m); return -1; @@ -497,7 +498,7 @@ static struct mscp_thread *mscp_copy_thread_spawn(struct mscp *m, int id) t = malloc(sizeof(*t)); if (!t){ - mscp_set_error("malloc: %s,", strerrno()); + priv_set_errv("malloc: %s,", strerrno()); return NULL; } @@ -511,7 +512,7 @@ static struct mscp_thread *mscp_copy_thread_spawn(struct mscp *m, int id) ret = pthread_create(&t->tid, NULL, mscp_copy_thread, t); if (ret < 0) { - mscp_set_error("pthread_create error: %d", ret); + priv_set_errv("pthread_create error: %d", ret); free(t); return NULL; } @@ -526,7 +527,7 @@ int mscp_start(struct mscp *m) int n, ret = 0; if ((n = chunk_pool_size(&m->cp)) < m->opts->nr_threads) { - mpr_notice("we have only %d chunk(s). " + pr_notice("we have only %d chunk(s). " "set number of connections to %d", n, n); m->opts->nr_threads = n; } @@ -534,7 +535,7 @@ int mscp_start(struct mscp *m) for (n = 0; n < m->opts->nr_threads; n++) { t = mscp_copy_thread_spawn(m, n); if (!t) { - mpr_err("failed to spawn copy thread"); + pr_err("failed to spawn copy thread"); break; } RWLOCK_WRITE_ACQUIRE(&m->thread_rwlock); @@ -582,7 +583,7 @@ int mscp_join(struct mscp *m) } } - mpr_notice("%lu/%lu bytes copied for %lu/%lu files", + pr_notice("%lu/%lu bytes copied for %lu/%lu files", done, m->total_bytes, nr_copied, nr_tobe_copied); return ret; @@ -627,29 +628,29 @@ void *mscp_copy_thread(void *arg) } if (sem_wait(m->sem) < 0) { - mpr_err("sem_wait: %s", strerrno()); + pr_err("sem_wait: %s", strerrno()); goto err_out; } if (!(nomore = chunk_pool_is_empty(&m->cp))) { if (m->opts->interval > 0) wait_for_interval(m->opts->interval); - mpr_notice("thread:%d connecting to %s", t->id, m->remote); + pr_notice("thread:%d connecting to %s", t->id, m->remote); t->sftp = ssh_init_sftp_session(m->remote, m->ssh_opts); } if (sem_post(m->sem) < 0) { - mpr_err("sem_post: %s", strerrno()); + pr_err("sem_post: %s", strerrno()); goto err_out; } if (nomore) { - mpr_notice("thread:%d no more connections needed", t->id); + pr_notice("thread:%d no more connections needed", t->id); goto out; } if (!t->sftp) { - mpr_err("thread:%d: %s", t->id, mscp_get_error()); + pr_err("thread:%d: %s", t->id, priv_get_err()); goto err_out; } @@ -685,8 +686,8 @@ void *mscp_copy_thread(void *arg) pthread_cleanup_pop(1); if (t->ret < 0) - mpr_err("thread:%d copy failed: %s 0x%010lx-0x%010lx", - t->id, c->p->path, c->off, c->off + c->len); + pr_err("thread:%d copy failed: %s 0x%010lx-0x%010lx", + t->id, c->p->path, c->off, c->off + c->len); return NULL; @@ -777,3 +778,4 @@ void mscp_get_stats(struct mscp *m, struct mscp_stats *s) s->finished = nr_threads > 0 ? (nr_finished == nr_threads) : false; } + @@ -7,12 +7,13 @@ #include <assert.h> #include <ssh.h> -#include <util.h> +#include <minmax.h> #include <fileops.h> #include <list.h> #include <atomic.h> #include <path.h> -#include <message.h> +#include <strerrno.h> +#include <print.h> /* chunk pool operations */ #define CHUNK_POOL_STATE_FILLING 0 @@ -103,7 +104,7 @@ static char *resolve_dst_path(const char *src_file_path, struct path_resolve_arg strncpy(copy, a->src_path, PATH_MAX); prefix = dirname(copy); if (!prefix) { - mscp_set_error("dirname: %s", strerrno()); + priv_set_errv("dirname: %s", strerrno()); return NULL; } @@ -146,11 +147,11 @@ static char *resolve_dst_path(const char *src_file_path, struct path_resolve_arg a->dst_path, src_file_path + strlen(a->src_path) + 1); if (ret >= PATH_MAX) { - mpr_warn("Too long path: %s", dst_file_path); + pr_warn("Too long path: %s", dst_file_path); return NULL; } - mpr_debug("file: %s -> %s", src_file_path, dst_file_path); + pr_debug("file: %s -> %s", src_file_path, dst_file_path); return strndup(dst_file_path, PATH_MAX); } @@ -161,7 +162,7 @@ static struct chunk *alloc_chunk(struct path *p) struct chunk *c; if (!(c = malloc(sizeof(*c)))) { - mscp_set_error("malloc %s", strerrno()); + priv_set_errv("malloc %s", strerrno()); return NULL; } memset(c, 0, sizeof(*c)); @@ -223,7 +224,7 @@ static int append_path(sftp_session sftp, const char *path, struct stat st, struct path *p; if (!(p = malloc(sizeof(*p)))) { - mscp_set_error("failed to allocate memory: %s", strerrno()); + priv_set_errv("failed to allocate memory: %s", strerrno()); return -1; } @@ -275,7 +276,7 @@ static int walk_path_recursive(sftp_session sftp, const char *path, int ret; if (mscp_stat(path, &st, sftp) < 0) { - mpr_err("stat: %s: %s", path, strerrno()); + pr_err("stat: %s: %s", path, strerrno()); return -1; } @@ -289,7 +290,7 @@ static int walk_path_recursive(sftp_session sftp, const char *path, /* ok, this path is a directory. walk through it. */ if (!(d = mscp_opendir(path, sftp))) { - mpr_err("opendir: %s: %s", path, strerrno()); + pr_err("opendir: %s: %s", path, strerrno()); return -1; } @@ -299,7 +300,7 @@ static int walk_path_recursive(sftp_session sftp, const char *path, ret = snprintf(next_path, PATH_MAX, "%s/%s", path, e->d_name); if (ret >= PATH_MAX) { - mpr_warn("Too long path: %s/%s", path, e->d_name); + pr_warn("Too long path: %s/%s", path, e->d_name); continue; } @@ -354,7 +355,7 @@ static int touch_dst_path(struct path *p, sftp_session sftp) if (S_ISDIR(st.st_mode)) goto next; /* directory exists. go deeper */ else { - mscp_set_error("mscp_stat %s: not a directory", path); + priv_set_errv("mscp_stat %s: not a directory", path); return -1; /* path exists, but not directory. */ } } @@ -362,7 +363,7 @@ static int touch_dst_path(struct path *p, sftp_session sftp) if (errno == ENOENT) { /* no file on the path. create directory. */ if (mscp_mkdir(path, mode, sftp) < 0) { - mscp_set_error("mscp_mkdir %s: %s", path, strerrno()); + priv_set_errv("mscp_mkdir %s: %s", path, strerrno()); return -1; } } @@ -374,7 +375,7 @@ static int touch_dst_path(struct path *p, sftp_session sftp) * end. see https://bugzilla.mindrot.org/show_bug.cgi?id=3431 */ f = mscp_open(p->dst_path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR, sftp); if (!f) { - mscp_set_error("mscp_open %s: %s\n", p->dst_path, strerrno()); + priv_set_errv("mscp_open %s: %s\n", p->dst_path, strerrno()); return -1; } @@ -391,11 +392,11 @@ static int prepare_dst_path(struct path *p, sftp_session dst_sftp) if (p->state == FILE_STATE_INIT) { if (touch_dst_path(p, dst_sftp) < 0) { ret = -1; - mpr_err("failed to prepare dst path: %s", mscp_get_error()); + pr_err("failed to prepare dst path: %s", priv_get_err()); goto out; } p->state = FILE_STATE_OPENED; - mpr_info("copy start: %s", p->path); + pr_info("copy start: %s", p->path); } out: @@ -431,7 +432,7 @@ static int copy_chunk_l2r(struct chunk *c, int fd, sftp_file sf, reqs[idx].len = sftp_async_write(sf, read_to_buf, reqs[idx].len, &fd, &reqs[idx].id); if (reqs[idx].len < 0) { - mscp_set_error("sftp_async_write: %s or %s", + priv_set_errv("sftp_async_write: %s or %s", sftp_get_ssh_error(sf->sftp), strerrno()); return -1; } @@ -441,7 +442,7 @@ static int copy_chunk_l2r(struct chunk *c, int fd, sftp_file sf, for (idx = 0; remaind > 0; idx = (idx + 1) % nr_ahead) { ret = sftp_async_write_end(sf, reqs[idx].id, 1); if (ret != SSH_OK) { - mscp_set_error("sftp_async_write_end: %s", + priv_set_errv("sftp_async_write_end: %s", sftp_get_ssh_error(sf->sftp)); return -1; } @@ -459,7 +460,7 @@ static int copy_chunk_l2r(struct chunk *c, int fd, sftp_file sf, reqs[idx].len = sftp_async_write(sf, read_to_buf, reqs[idx].len, &fd, &reqs[idx].id); if (reqs[idx].len < 0) { - mscp_set_error("sftp_async_write: %s or %s", + priv_set_errv("sftp_async_write: %s or %s", sftp_get_ssh_error(sf->sftp), strerrno()); return -1; } @@ -467,7 +468,7 @@ static int copy_chunk_l2r(struct chunk *c, int fd, sftp_file sf, } if (remaind < 0) { - mscp_set_error("invalid remaind bytes %ld. " + priv_set_errv("invalid remaind bytes %ld. " "last async_write_end bytes %lu.", remaind, reqs[idx].len); return -1; @@ -497,7 +498,7 @@ static int copy_chunk_r2l(struct chunk *c, sftp_file sf, int fd, reqs[idx].len = min(thrown, sizeof(buf)); reqs[idx].id = sftp_async_read_begin(sf, reqs[idx].len); if (reqs[idx].id < 0) { - mscp_set_error("sftp_async_read_begin: %d", + priv_set_errv("sftp_async_read_begin: %d", sftp_get_error(sf->sftp)); return -1; } @@ -507,7 +508,7 @@ static int copy_chunk_r2l(struct chunk *c, sftp_file sf, int fd, for (idx = 0; remaind > 0; idx = (idx + 1) % nr_ahead) { read_bytes = sftp_async_read(sf, buf, reqs[idx].len, reqs[idx].id); if (read_bytes == SSH_ERROR) { - mscp_set_error("sftp_async_read: %d", + priv_set_errv("sftp_async_read: %d", sftp_get_error(sf->sftp)); return -1; } @@ -520,12 +521,12 @@ static int copy_chunk_r2l(struct chunk *c, sftp_file sf, int fd, write_bytes = write(fd, buf, read_bytes); if (write_bytes < 0) { - mscp_set_error("write: %s", strerrno()); + priv_set_errv("write: %s", strerrno()); return -1; } if (write_bytes < read_bytes) { - mscp_set_error("failed to write full bytes"); + priv_set_errv("failed to write full bytes"); return -1; } @@ -534,7 +535,7 @@ static int copy_chunk_r2l(struct chunk *c, sftp_file sf, int fd, } if (remaind < 0) { - mscp_set_error("invalid remaind bytes %ld. last async_read bytes %ld. " + priv_set_errv("invalid remaind bytes %ld. last async_read bytes %ld. " "last write bytes %ld", remaind, read_bytes, write_bytes); return -1; @@ -573,11 +574,11 @@ int copy_chunk(struct chunk *c, sftp_session src_sftp, sftp_session dst_sftp, mode = S_IRUSR; s = mscp_open(c->p->path, flags, mode, src_sftp); if (!s) { - mscp_set_error("mscp_open: %s: %s", c->p->path, strerrno()); + priv_set_errv("mscp_open: %s: %s", c->p->path, strerrno()); return -1; } if (mscp_lseek(s, c->off) < 0) { - mscp_set_error("mscp_lseek: %s: %s", c->p->path, strerrno()); + priv_set_errv("mscp_lseek: %s: %s", c->p->path, strerrno()); return -1; } @@ -587,20 +588,20 @@ int copy_chunk(struct chunk *c, sftp_session src_sftp, sftp_session dst_sftp, d = mscp_open(c->p->dst_path, flags, mode, dst_sftp); if (!d) { mscp_close(s); - mscp_set_error("mscp_open: %s: %s", c->p->dst_path, strerrno()); + priv_set_errv("mscp_open: %s: %s", c->p->dst_path, strerrno()); return -1; } if (mscp_lseek(d, c->off) < 0) { - mscp_set_error("mscp_lseek: %s: %s", c->p->dst_path, strerrno()); + priv_set_errv("mscp_lseek: %s: %s", c->p->dst_path, strerrno()); return -1; } - mpr_debug("copy chunk start: %s 0x%lx-0x%lx", + pr_debug("copy chunk start: %s 0x%lx-0x%lx", c->p->path, c->off, c->off + c->len); ret = _copy_chunk(c, s, d, nr_ahead, buf_sz, counter); - mpr_debug("copy chunk done: %s 0x%lx-0x%lx", + pr_debug("copy chunk done: %s 0x%lx-0x%lx", c->p->path, c->off, c->off + c->len); @@ -615,14 +616,14 @@ int copy_chunk(struct chunk *c, sftp_session src_sftp, sftp_session dst_sftp, /* sync stat */ if (mscp_stat(c->p->path, &st, src_sftp) < 0) { - mpr_err("mscp_stat: %s: %s", c->p->path, strerrno()); + pr_err("mscp_stat: %s: %s", c->p->path, strerrno()); return -1; } if (mscp_setstat(c->p->dst_path, &st, preserve_ts, dst_sftp) < 0) { - mpr_err("mscp_setstat: %s: %s", c->p->path, strerrno()); + pr_err("mscp_setstat: %s: %s", c->p->path, strerrno()); return -1; } - mpr_info("copy done: %s", c->p->path); + pr_info("copy done: %s", c->p->path); } return ret; @@ -10,7 +10,6 @@ #include <list.h> #include <atomic.h> #include <ssh.h> -#include <message.h> struct path { struct list_head list; /* mscp->path_list */ diff --git a/src/platform.c b/src/platform.c index 668c571..e3d1421 100644 --- a/src/platform.c +++ b/src/platform.c @@ -22,9 +22,9 @@ #error unsupported platform #endif -#include <util.h> #include <platform.h> -#include <message.h> +#include <strerrno.h> +#include <print.h> #ifdef __APPLE__ @@ -34,7 +34,7 @@ int nr_cpus() size_t size = sizeof(n); if (sysctlbyname("machdep.cpu.core_count", &n, &size, NULL, 0) != 0) { - mscp_set_error("failed to get number of cpu cores: %s", strerrno()); + priv_set_errv("failed to get number of cpu cores: %s", strerrno()); return -1; } @@ -43,7 +43,7 @@ int nr_cpus() int set_thread_affinity(pthread_t tid, int core) { - pr_warn("setting thread afinity is not implemented on apple\n"); + pr_warn("setting thread afinity is not implemented on apple"); return 0; } @@ -124,8 +124,8 @@ int set_thread_affinity(pthread_t tid, int core) CPU_SET(core, &target_cpu_set); ret = pthread_setaffinity_np(tid, sizeof(target_cpu_set), &target_cpu_set); if (ret < 0) - mscp_set_error("failed to set thread/cpu affinity for core %d: %s", - core, strerrno()); + priv_set_errv("failed to set thread/cpu affinity for core %d: %s", + core, strerrno()); return ret; } diff --git a/src/print.c b/src/print.c new file mode 100644 index 0000000..12426fe --- /dev/null +++ b/src/print.c @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ + +#include <print.h> + +/* message print functions */ +static int __print_severity = MSCP_SEVERITY_WARN; + +void set_print_severity(int serverity) +{ + if (serverity < 0) + __print_severity = -1; /* no print */ + __print_severity = serverity; +} + +int get_print_severity() +{ + return __print_severity; +} + diff --git a/src/print.h b/src/print.h new file mode 100644 index 0000000..c0b3359 --- /dev/null +++ b/src/print.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include <libgen.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <mscp.h> + +/* message print. printed messages are passed to application via msg_fd */ +void set_print_severity(int severity); +int get_print_severity(); + +#define __print(fp, severity, fmt, ...) \ + do { \ + if (severity <= get_print_severity()) { \ + fprintf(fp, "\r\033[K" fmt "\n", ##__VA_ARGS__); \ + fflush(fp); \ + } \ + } while (0) + +#define pr_err(fmt, ...) \ + __print(stderr, MSCP_SEVERITY_ERR, fmt, ##__VA_ARGS__) +#define pr_warn(fmt, ...) \ + __print(stderr, MSCP_SEVERITY_WARN, fmt, ##__VA_ARGS__) +#define pr_notice(fmt, ...) \ + __print(stdout, MSCP_SEVERITY_NOTICE, fmt, ##__VA_ARGS__) +#define pr_info(fmt, ...) \ + __print(stdout, MSCP_SEVERITY_INFO, fmt, ##__VA_ARGS__) +#define pr_debug(fmt, ...) \ + __print(stdout, MSCP_SEVERITY_DEBUG, fmt, ##__VA_ARGS__) + +#endif /* _PRINT_H_ */ @@ -7,8 +7,8 @@ #include "libssh/callbacks.h" #include <ssh.h> -#include <util.h> -#include <message.h> +#include <mscp.h> +#include <strerrno.h> static int ssh_verify_known_hosts(ssh_session session); @@ -18,53 +18,53 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts) if (opts->login_name && ssh_options_set(ssh, SSH_OPTIONS_USER, opts->login_name) < 0) { - mscp_set_error("failed to set login name"); + priv_set_errv("failed to set login name"); return -1; } if (opts->port && ssh_options_set(ssh, SSH_OPTIONS_PORT_STR, opts->port) < 0) { - mscp_set_error("failed to set port number"); + priv_set_errv("failed to set port number"); return -1; } if (opts->identity && ssh_options_set(ssh, SSH_OPTIONS_IDENTITY, opts->identity) < 0) { - mscp_set_error("failed to set identity"); + priv_set_errv("failed to set identity"); return -1; } if (opts->cipher) { if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_C_S, opts->cipher) < 0) { - mscp_set_error("failed to set cipher for client to server"); + priv_set_errv("failed to set cipher for client to server"); return -1; } if (ssh_options_set(ssh, SSH_OPTIONS_CIPHERS_S_C, opts->cipher) < 0) { - mscp_set_error("failed to set cipher for server to client"); + priv_set_errv("failed to set cipher for server to client"); return -1; } } if (opts->hmac) { if (ssh_options_set(ssh, SSH_OPTIONS_HMAC_C_S, opts->hmac) < 0) { - mscp_set_error("failed to set hmac for client to server"); + priv_set_errv("failed to set hmac for client to server"); return -1; } if (ssh_options_set(ssh, SSH_OPTIONS_HMAC_S_C, opts->hmac) < 0) { - mscp_set_error("failed to set hmac for server to client"); + priv_set_errv("failed to set hmac for server to client"); return -1; } } if (opts->compress && ssh_options_set(ssh, SSH_OPTIONS_COMPRESSION, opts->compress) < 0) { - mscp_set_error("failed to enable ssh compression"); + priv_set_errv("failed to enable ssh compression"); return -1; } if (opts->ccalgo && ssh_options_set(ssh, SSH_OPTIONS_CCALGO, opts->ccalgo) < 0) { - mscp_set_error("failed to set cclago"); + priv_set_errv("failed to set cclago"); return -1; } @@ -72,14 +72,14 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts) if (!opts->enable_nagle) { int v = 1; if (ssh_options_set(ssh, SSH_OPTIONS_NODELAY, &v) < 0) { - mscp_set_error("failed to set TCP_NODELAY"); + priv_set_errv("failed to set TCP_NODELAY"); return -1; } } if (opts->config && ssh_options_parse_config(ssh, opts->config) < 0) { - mscp_set_error("failed to parse ssh_config: %s", opts->config); + priv_set_errv("failed to parse ssh_config: %s", opts->config); return -1; } @@ -112,10 +112,11 @@ static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts) if (!opts->password) { char buf[128] = {}; if (ssh_getpass("Password: ", buf, sizeof(buf), 0, 0) < 0) { + priv_set_errv("ssh_getpass failed"); return -1; } if (!(opts->password = strndup(buf, sizeof(buf)))) { - mpr_err("strndup: %s", strerrno()); + priv_set_errv("strndup: %s", strerrno()); return -1; } } @@ -149,7 +150,7 @@ static int ssh_cache_passphrase(const char *prompt, char *buf, size_t len, int e free(opts->passphrase); if (!(opts->passphrase = strndup(buf, len))) { - mpr_err("strndup: %s", strerrno()); + priv_set_errv("strndup: %s", strerrno()); return -1; } @@ -171,7 +172,7 @@ static ssh_session ssh_init_session(const char *sshdst, struct mscp_ssh_opts *op ssh_set_callbacks(ssh, &cb); if (ssh_options_set(ssh, SSH_OPTIONS_HOST, sshdst) != SSH_OK) { - mscp_set_error("failed to set destination host"); + priv_set_errv("failed to set destination host"); goto free_out; } @@ -179,12 +180,12 @@ static ssh_session ssh_init_session(const char *sshdst, struct mscp_ssh_opts *op goto free_out; if (ssh_connect(ssh) != SSH_OK) { - mscp_set_error("failed to connect ssh server: %s", ssh_get_error(ssh)); + priv_set_errv("failed to connect ssh server: %s", ssh_get_error(ssh)); goto free_out; } if (ssh_authenticate(ssh, opts) != 0) { - mscp_set_error("authentication failed: %s", ssh_get_error(ssh)); + priv_set_errv("authentication failed: %s", ssh_get_error(ssh)); goto disconnect_out; } @@ -212,13 +213,13 @@ sftp_session ssh_init_sftp_session(const char *sshdst, struct mscp_ssh_opts *opt sftp = sftp_new(ssh); if (!sftp) { - mscp_set_error("failed to allocate sftp session: %s", + priv_set_errv("failed to allocate sftp session: %s", ssh_get_error(ssh)); goto err_out; } if (sftp_init(sftp) != SSH_OK) { - mscp_set_error("failed to initialize sftp session: err code %d", + priv_set_errv("failed to initialize sftp session: err code %d", sftp_get_error(sftp)); goto err_out; } @@ -305,13 +306,13 @@ static int ssh_verify_known_hosts(ssh_session session) rc = ssh_session_update_known_hosts(session); if (rc < 0) { - fprintf(stderr, "Error %s\n", strerror(errno)); + priv_set_errv("%s", ssh_get_error(session)); return -1; } break; case SSH_KNOWN_HOSTS_ERROR: - fprintf(stderr, "Error %s", ssh_get_error(session)); + priv_set_errv("known hosts error: %s", ssh_get_error(session)); ssh_clean_pubkey_hash(&hash); return -1; } diff --git a/src/strerrno.c b/src/strerrno.c new file mode 100644 index 0000000..39391d5 --- /dev/null +++ b/src/strerrno.c @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> + +#include <strerrno.h> + +#define STRERRNO_TLS_BUFSIZ 128 +__thread char tls_strerrno_buf[STRERRNO_TLS_BUFSIZ]; + +const char *strerrno(void) +{ + snprintf(tls_strerrno_buf, sizeof(tls_strerrno_buf), "%s", "strerror_r error"); + strerror_r(errno, tls_strerrno_buf, sizeof(tls_strerrno_buf)); + return tls_strerrno_buf; +} + +#define PRIV_ERR_BUFSIZ (1 << 12) +static char priv_err_buf[PRIV_ERR_BUFSIZ], internal[PRIV_ERR_BUFSIZ]; + +void priv_set_err(const char *fmt, ...) +{ + va_list va; + + /* arguments may contains priv_err_buf. Thus, we build the + * string in a internal buffer, and then copy it to + * priv_err_buf. */ + memset(internal, 0, sizeof(internal)); + va_start(va, fmt); + vsnprintf(internal, sizeof(internal), fmt, va); + va_end(va); + + snprintf(priv_err_buf, sizeof(priv_err_buf), "%s", internal); +} + +const char *priv_get_err() +{ + return priv_err_buf; +} diff --git a/src/strerrno.h b/src/strerrno.h new file mode 100644 index 0000000..e000c86 --- /dev/null +++ b/src/strerrno.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-3.0-only */ +#ifndef _STRERRNO_ +#define _STRERRNO_ + +#include <libgen.h> /* basename() */ + +/** + * strerrno() returns error message string corresponding to errno. + * strerrno() is thread safe. + */ +const char *strerrno(void); + +/** + * priv_set_err() sets an error message into a private buffer. This + * error message set by priv_set_err() can be accessed via + * priv_get_err(). priv_*_err functions are not thread safe. + */ +void priv_set_err(const char *fmt, ...); + +/** + * priv_set_errv(), a wrapper for priv_set_err(), just adds filename, + * line, and function name to the error message. + */ +#define priv_set_errv(fmt, ...) \ + priv_set_err("[%s:%d:%s] " fmt "\0", \ + basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__) + +/** + * priv_get_err() gets the error message sotred in a private buffer. + */ +const char *priv_get_err(); + +#endif /* _STRERRNO_ */ diff --git a/src/util.h b/src/util.h deleted file mode 100644 index e678db0..0000000 --- a/src/util.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-3.0-only */ -#ifndef _UTIL_H_ -#define _UTIL_H_ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <libgen.h> - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - - -#define pr(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) - -#define pr_info(fmt, ...) fprintf(stderr, "INFO:%s(): " fmt, \ - __func__, ##__VA_ARGS__) - -#define pr_warn(fmt, ...) fprintf(stderr, "\x1b[1m\x1b[33m" \ - "WARN:%s():\x1b[0m " fmt, \ - __func__, ##__VA_ARGS__) - -#define pr_err(fmt, ...) fprintf(stderr, "\x1b[1m\x1b[31m" \ - "ERR:%s:%d:%s():\x1b[0m " fmt, \ - basename(__FILE__), __LINE__, __func__, ##__VA_ARGS__) - -#ifdef DEBUG -#define pr_debug(fmt, ...) fprintf(stderr, "\x1b[1m\x1b[33m" \ - "DEBUG:%s():\x1b[0m " fmt, \ - __func__, ##__VA_ARGS__); -#else -#define pr_debug(fmt, ...) -#endif - - -#define min(a, b) (((a) > (b)) ? (b) : (a)) -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -#endif /* _UTIL_H_ */ |