Commit d6fe4819 authored by Thomas Haller's avatar Thomas Haller

systemd: merge branch systemd into master

parents c68c199e 5d020e1c
Pipeline #80634 canceled with stage
......@@ -1711,6 +1711,7 @@ shared_systemd_libnm_systemd_shared_la_SOURCES = \
shared/systemd/sd-adapt-shared/copy.h \
shared/systemd/sd-adapt-shared/def.h \
shared/systemd/sd-adapt-shared/device-nodes.h \
shared/systemd/sd-adapt-shared/dhcp-server-internal.h \
shared/systemd/sd-adapt-shared/dirent-util.h \
shared/systemd/sd-adapt-shared/errno-list.h \
shared/systemd/sd-adapt-shared/glob-util.h \
......@@ -1719,6 +1720,10 @@ shared_systemd_libnm_systemd_shared_la_SOURCES = \
shared/systemd/sd-adapt-shared/locale-util.h \
shared/systemd/sd-adapt-shared/memfd-util.h \
shared/systemd/sd-adapt-shared/missing.h \
shared/systemd/sd-adapt-shared/missing_fs.h \
shared/systemd/sd-adapt-shared/missing_magic.h \
shared/systemd/sd-adapt-shared/missing_network.h \
shared/systemd/sd-adapt-shared/missing_shed.h \
shared/systemd/sd-adapt-shared/missing_syscall.h \
shared/systemd/sd-adapt-shared/missing_timerfd.h \
shared/systemd/sd-adapt-shared/mkdir.h \
......@@ -1775,6 +1780,7 @@ shared_systemd_libnm_systemd_shared_la_SOURCES = \
shared/systemd/src/basic/mempool.c \
shared/systemd/src/basic/mempool.h \
shared/systemd/src/basic/missing_fcntl.h \
shared/systemd/src/basic/missing_random.h \
shared/systemd/src/basic/missing_socket.h \
shared/systemd/src/basic/missing_stat.h \
shared/systemd/src/basic/missing_type.h \
......@@ -1898,6 +1904,7 @@ src_libnm_systemd_core_la_SOURCES = \
src/systemd/src/systemd/_sd-common.h \
src/systemd/src/systemd/sd-dhcp-client.h \
src/systemd/src/systemd/sd-dhcp-lease.h \
src/systemd/src/systemd/sd-dhcp-option.h \
src/systemd/src/systemd/sd-dhcp6-client.h \
src/systemd/src/systemd/sd-dhcp6-lease.h \
src/systemd/src/systemd/sd-event.h \
......
#pragma once
/* dummy header */
......@@ -6,7 +6,6 @@
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "alloc-util.h"
......
......@@ -8,7 +8,6 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include "alloc-util.h"
......
......@@ -5,7 +5,6 @@
#include <errno.h>
#include <fcntl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <unistd.h>
......@@ -18,7 +17,8 @@
#include "io-util.h"
#include "macro.h"
#include "memfd-util.h"
#include "missing.h"
#include "missing_fcntl.h"
#include "missing_syscall.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
......
......@@ -10,7 +10,6 @@
#include <stdint.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
......@@ -22,7 +21,6 @@
#include "hexdecoct.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "mkdir.h"
#include "parse-util.h"
#include "path-util.h"
......@@ -312,6 +310,113 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
return 1;
}
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size) {
_cleanup_free_ char *buf = NULL;
_cleanup_close_ int fd = -1;
struct stat st;
size_t n, size;
int n_retries;
char *p;
assert(ret_contents);
/* Virtual filesystems such as sysfs or procfs use kernfs, and kernfs can work
* with two sorts of virtual files. One sort uses "seq_file", and the results of
* the first read are buffered for the second read. The other sort uses "raw"
* reads which always go direct to the device. In the latter case, the content of
* the virtual file must be retrieved with a single read otherwise a second read
* might get the new value instead of finding EOF immediately. That's the reason
* why the usage of fread(3) is prohibited in this case as it always performs a
* second call to read(2) looking for EOF. See issue 13585. */
fd = open(filename, O_RDONLY|O_CLOEXEC);
if (fd < 0)
return -errno;
/* Start size for files in /proc which usually report a file size of 0. */
size = LINE_MAX / 2;
/* Limit the number of attempts to read the number of bytes returned by fstat(). */
n_retries = 3;
for (;;) {
if (n_retries <= 0)
return -EIO;
if (fstat(fd, &st) < 0)
return -errno;
if (!S_ISREG(st.st_mode))
return -EBADF;
/* Be prepared for files from /proc which generally report a file size of 0. */
if (st.st_size > 0) {
size = st.st_size;
n_retries--;
} else
size = size * 2;
if (size > READ_FULL_BYTES_MAX)
return -E2BIG;
p = realloc(buf, size + 1);
if (!p)
return -ENOMEM;
buf = TAKE_PTR(p);
for (;;) {
ssize_t k;
/* Read one more byte so we can detect whether the content of the
* file has already changed or the guessed size for files from /proc
* wasn't large enough . */
k = read(fd, buf, size + 1);
if (k >= 0) {
n = k;
break;
}
if (errno != -EINTR)
return -errno;
}
/* Consider a short read as EOF */
if (n <= size)
break;
/* Hmm... either we read too few bytes from /proc or less likely the content
* of the file might have been changed (and is now bigger) while we were
* processing, let's try again either with a bigger guessed size or the new
* file size. */
if (lseek(fd, 0, SEEK_SET) < 0)
return -errno;
}
if (n < size) {
p = realloc(buf, n + 1);
if (!p)
return -ENOMEM;
buf = TAKE_PTR(p);
}
if (!ret_size) {
/* Safety check: if the caller doesn't want to know the size of what we
* just read it will rely on the trailing NUL byte. But if there's an
* embedded NUL byte, then we should refuse operation as otherwise
* there'd be ambiguity about what we just read. */
if (memchr(buf, 0, n))
return -EBADMSG;
} else
*ret_size = n;
buf[n] = 0;
*ret_contents = TAKE_PTR(buf);
return 0;
}
#endif /* NM_IGNORED */
int read_full_stream_full(
......@@ -346,9 +451,9 @@ int read_full_stream_full(
if (st.st_size > READ_FULL_BYTES_MAX)
return -E2BIG;
/* Start with the right file size, but be prepared for files from /proc which generally report a file
* size of 0. Note that we increase the size to read here by one, so that the first read attempt
* already makes us notice the EOF. */
/* Start with the right file size. Note that we increase the size
* to read here by one, so that the first read attempt already
* makes us notice the EOF. */
if (st.st_size > 0)
n_next = st.st_size + 1;
......@@ -508,7 +613,7 @@ int get_proc_field(const char *filename, const char *pattern, const char *termin
assert(pattern);
assert(field);
r = read_full_file(filename, &status, NULL);
r = read_full_virtual_file(filename, &status, NULL);
if (r < 0)
return r;
......
......@@ -56,6 +56,7 @@ int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **co
static inline int read_full_file(const char *filename, char **contents, size_t *size) {
return read_full_file_full(filename, 0, contents, size);
}
int read_full_virtual_file(const char *filename, char **ret_contents, size_t *ret_size);
int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size);
static inline int read_full_stream(FILE *f, char **contents, size_t *size) {
return read_full_stream_full(f, NULL, 0, contents, size);
......
......@@ -2,15 +2,26 @@
#include "nm-sd-adapt-shared.h"
#include <stdio.h>
#include "format-util.h"
#include "memory-util.h"
#include "stdio-util.h"
char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) {
assert_cc(DECIMAL_STR_MAX(int) + 1 <= IF_NAMESIZE + 1);
char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag) {
/* Buffer is always cleared */
memzero(buf, IF_NAMESIZE + 1);
return if_indextoname(ifindex, buf);
if (if_indextoname(ifindex, buf))
return buf;
if (!FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX))
return NULL;
if (FLAGS_SET(flag, FORMAT_IFNAME_IFINDEX_WITH_PERCENT))
snprintf(buf, IF_NAMESIZE + 1, "%%%d", ifindex);
else
snprintf(buf, IF_NAMESIZE + 1, "%d", ifindex);
return buf;
}
char *format_bytes_full(char *buf, size_t l, uint64_t t, FormatBytesFlag flag) {
......
......@@ -68,7 +68,15 @@
# error Unknown ino_t size
#endif
char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]);
typedef enum {
FORMAT_IFNAME_IFINDEX = 1 << 0,
FORMAT_IFNAME_IFINDEX_WITH_PERCENT = (1 << 1) | FORMAT_IFNAME_IFINDEX,
} FormatIfnameFlag;
char *format_ifname_full(int ifindex, char buf[static IF_NAMESIZE + 1], FormatIfnameFlag flag);
static inline char *format_ifname(int ifindex, char buf[static IF_NAMESIZE + 1]) {
return format_ifname_full(ifindex, buf, 0);
}
typedef enum {
FORMAT_BYTES_USE_IEC = 1 << 0,
......
This diff is collapsed.
......@@ -72,29 +72,28 @@ union inotify_event_buffer {
};
int inotify_add_watch_fd(int fd, int what, uint32_t mask);
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask);
enum {
CHASE_PREFIX_ROOT = 1 << 0, /* The specified path will be prefixed by the specified root before beginning the iteration */
CHASE_NONEXISTENT = 1 << 1, /* It's OK if the path doesn't actually exist. */
CHASE_NO_AUTOFS = 1 << 2, /* Return -EREMOTE if autofs mount point found */
CHASE_SAFE = 1 << 3, /* Return EPERM if we ever traverse from unprivileged to privileged files or directories */
CHASE_OPEN = 1 << 4, /* Return an O_PATH object to the final component */
CHASE_TRAIL_SLASH = 1 << 5, /* Any trailing slash will be preserved */
CHASE_STEP = 1 << 6, /* Just execute a single step of the normalization */
CHASE_NOFOLLOW = 1 << 7, /* Do not follow the path's right-most compontent. With CHASE_OPEN, when
* the path's right-most component refers to symlink, return O_PATH fd of
* the symlink. */
CHASE_WARN = 1 << 8, /* Emit an appropriate warning when an error is encountered */
CHASE_TRAIL_SLASH = 1 << 4, /* Any trailing slash will be preserved */
CHASE_STEP = 1 << 5, /* Just execute a single step of the normalization */
CHASE_NOFOLLOW = 1 << 6, /* Do not follow the path's right-most compontent. With ret_fd, when the path's
* right-most component refers to symlink, return O_PATH fd of the symlink. */
CHASE_WARN = 1 << 7, /* Emit an appropriate warning when an error is encountered */
};
/* How many iterations to execute before returning -ELOOP */
#define CHASE_SYMLINKS_MAX 32
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret);
int chase_symlinks(const char *path_with_prefix, const char *root, unsigned flags, char **ret_path, int *ret_fd);
int chase_symlinks_and_open(const char *path, const char *root, unsigned chase_flags, int open_flags, char **ret_path);
int chase_symlinks_and_opendir(const char *path, const char *root, unsigned chase_flags, char **ret_path, DIR **ret_dir);
int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat);
int chase_symlinks_and_stat(const char *path, const char *root, unsigned chase_flags, char **ret_path, struct stat *ret_stat, int *ret_fd);
/* Useful for usage with _cleanup_(), removes a directory and frees the pointer */
static inline void rmdir_and_free(char *p) {
......
......@@ -55,11 +55,7 @@ void path_hash_func(const char *q, struct siphash *state) {
}
}
int path_compare_func(const char *a, const char *b) {
return path_compare(a, b);
}
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare_func);
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
#endif /* NM_IGNORED */
void trivial_hash_func(const void *p, struct siphash *state) {
......
......@@ -79,7 +79,6 @@ extern const struct hash_ops string_hash_ops;
extern const struct hash_ops string_hash_ops_free_free;
void path_hash_func(const char *p, struct siphash *state);
int path_compare_func(const char *a, const char *b) _pure_;
extern const struct hash_ops path_hash_ops;
/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
......
......@@ -5,7 +5,6 @@
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "fileio.h"
......@@ -13,7 +12,7 @@
#include "macro.h"
#include "memory-util.h"
#include "mempool.h"
#include "missing.h"
#include "missing_syscall.h"
#include "process-util.h"
#include "random-util.h"
#include "set.h"
......
......@@ -5,7 +5,6 @@
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
#include <unistd.h>
......
......@@ -6,7 +6,6 @@
#include <limits.h>
#include <poll.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "io-util.h"
......
......@@ -316,17 +316,18 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
extern void __coverity_panic__(void);
static inline int __coverity_check__(int condition) {
static inline void __coverity_check__(int condition) {
if (!condition)
__coverity_panic__();
}
static inline int __coverity_check_and_return__(int condition) {
return condition;
}
#define assert_message_se(expr, message) \
do { \
if (__coverity_check__(!(expr))) \
__coverity_panic__(); \
} while (false)
#define assert_message_se(expr, message) __coverity_check__(!!(expr))
#define assert_log(expr, message) __coverity_check__(!!(expr))
#define assert_log(expr, message) __coverity_check_and_return__(!!(expr))
#else /* ! __COVERITY__ */
......
......@@ -11,6 +11,7 @@
size_t page_size(void) _pure_;
#define PAGE_ALIGN(l) ALIGN_TO((l), page_size())
#define PAGE_ALIGN_DOWN(l) (l & ~(page_size() - 1))
/* Normal memcpy requires src to be nonnull. We do nothing if n is 0. */
static inline void memcpy_safe(void *dst, const void *src, size_t n) {
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#if USE_SYS_RANDOM_H
# include <sys/random.h>
#else
# include <linux/random.h>
#endif
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
#ifndef GRND_RANDOM
#define GRND_RANDOM 0x0002
#endif
......@@ -5,11 +5,9 @@
#include <errno.h>
#include <inttypes.h>
#include <linux/oom.h>
#include <locale.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include "alloc-util.h"
......@@ -17,7 +15,7 @@
#include "extract-word.h"
#include "locale-util.h"
#include "macro.h"
#include "missing.h"
#include "missing_network.h"
#include "parse-util.h"
#include "process-util.h"
#include "stat-util.h"
......
......@@ -6,8 +6,6 @@
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
/* When we include libgen.h because we need dirname() we immediately
......@@ -22,7 +20,6 @@
#include "glob-util.h"
#include "log.h"
#include "macro.h"
#include "missing.h"
#include "nulstr-util.h"
#include "parse-util.h"
#include "path-util.h"
......@@ -276,7 +273,7 @@ char **path_strv_resolve(char **l, const char *root) {
} else
t = *s;
r = chase_symlinks(t, root, 0, &u);
r = chase_symlinks(t, root, 0, &u, NULL);
if (r == -ENOENT) {
if (root) {
u = TAKE_PTR(orig);
......@@ -658,7 +655,9 @@ int find_binary(const char *name, char **ret) {
return 0;
}
last_error = -errno;
/* PATH entries which we don't have access to are ignored, as per tradition. */
if (errno != EACCES)
last_error = -errno;
}
return last_error;
......
......@@ -12,42 +12,38 @@
#if 0 /* NM_IGNORED */
#define PATH_SPLIT_SBIN_BIN(x) x "sbin:" x "bin"
#define PATH_SPLIT_BIN_SBIN(x) x "bin:" x "sbin"
#define PATH_SPLIT_SBIN_BIN_NULSTR(x) x "sbin\0" x "bin\0"
#define PATH_NORMAL_SBIN_BIN(x) x "bin"
#define PATH_NORMAL_BIN_SBIN(x) x "bin"
#define PATH_NORMAL_SBIN_BIN_NULSTR(x) x "bin\0"
#if HAVE_SPLIT_BIN
# define PATH_SBIN_BIN(x) PATH_SPLIT_SBIN_BIN(x)
# define PATH_BIN_SBIN(x) PATH_SPLIT_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_SPLIT_SBIN_BIN_NULSTR(x)
#else
# define PATH_SBIN_BIN(x) PATH_NORMAL_SBIN_BIN(x)
# define PATH_BIN_SBIN(x) PATH_NORMAL_BIN_SBIN(x)
# define PATH_SBIN_BIN_NULSTR(x) PATH_NORMAL_SBIN_BIN_NULSTR(x)
#endif
#define DEFAULT_PATH_NORMAL PATH_SBIN_BIN("/usr/local/") ":" PATH_SBIN_BIN("/usr/")
#define DEFAULT_USER_PATH_NORMAL PATH_BIN_SBIN("/usr/local/") ":" PATH_BIN_SBIN("/usr/")
#define DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/usr/local/") PATH_SBIN_BIN_NULSTR("/usr/")
#define DEFAULT_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_SBIN_BIN("/")
#define DEFAULT_USER_PATH_SPLIT_USR DEFAULT_PATH_NORMAL ":" PATH_BIN_SBIN("/")
#define DEFAULT_PATH_SPLIT_USR_NULSTR DEFAULT_PATH_NORMAL_NULSTR PATH_SBIN_BIN_NULSTR("/")
#define DEFAULT_PATH_COMPAT PATH_SPLIT_SBIN_BIN("/usr/local/") ":" PATH_SPLIT_SBIN_BIN("/usr/") ":" PATH_SPLIT_SBIN_BIN("/")
#if HAVE_SPLIT_USR
# define DEFAULT_PATH DEFAULT_PATH_SPLIT_USR
# define DEFAULT_USER_PATH DEFAULT_USER_PATH_SPLIT_USR
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_SPLIT_USR_NULSTR
#else
# define DEFAULT_PATH DEFAULT_PATH_NORMAL
# define DEFAULT_USER_PATH DEFAULT_USER_PATH_NORMAL
# define DEFAULT_PATH_NULSTR DEFAULT_PATH_NORMAL_NULSTR
#endif
#endif /* NM_IGNORED */
#ifndef DEFAULT_USER_PATH
# define DEFAULT_USER_PATH DEFAULT_PATH
#endif
bool is_path(const char *p) _pure_;
int path_split_and_make_absolute(const char *p, char ***ret);
bool path_is_absolute(const char *p) _pure_;
......
......@@ -6,11 +6,9 @@
#include <errno.h>
#include <limits.h>
#include <linux/oom.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/personality.h>
......@@ -37,7 +35,8 @@
#include "log.h"
#include "macro.h"
#include "memory-util.h"
#include "missing.h"
#include "missing_sched.h"
#include "missing_syscall.h"
#include "namespace-util.h"
#include "process-util.h"
#include "raw-clone.h"
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <alloca.h>
#include <errno.h>
#include <sched.h>
#include <signal.h>
......
......@@ -19,17 +19,12 @@
# include <sys/auxv.h>
#endif
#if USE_SYS_RANDOM_H
# include <sys/random.h>
#else
# include <linux/random.h>
#endif
#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "io-util.h"
#include "missing.h"
#include "missing_random.h"
#include "missing_syscall.h"
#include "parse-util.h"
#include "random-util.h"
#include "siphash24.h"
......
......@@ -102,8 +102,8 @@ static inline void *set_steal_first(Set *s) {
/* no set_steal_first_key */
/* no set_first_key */
static inline void *set_first(Set *s) {
return internal_hashmap_first_key_and_value(HASHMAP_BASE(s), false, NULL);
static inline void *set_first(const Set *s) {
return internal_hashmap_first_key_and_value(HASHMAP_BASE((Set *) s), false, NULL);
}
/* no set_next */
......
......@@ -13,7 +13,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "alloc-util.h"
......@@ -25,7 +25,7 @@
#include "log.h"
#include "macro.h"
#include "memory-util.h"
#include "missing.h"
#include "missing_socket.h"
#include "parse-util.h"
#include "path-util.h"
#include "process-util.h"
......
......@@ -2,12 +2,9 @@
#include "nm-sd-adapt-shared.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/magic.h>
#include <sched.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/types.h>
#include <unistd.h>
......@@ -17,7 +14,8 @@
#include "fd-util.h"
#include "fs-util.h"
#include "macro.h"
#include "missing.h"
#include "missing_fs.h"
#include "missing_magic.h"
#include "parse-util.h"
#include "stat-util.h"
#include "string-util.h"
......@@ -340,7 +338,7 @@ int device_path_make_canonical(mode_t mode, dev_t devno, char **ret) {
if (r < 0)
return r;
return chase_symlinks(p, NULL, 0, ret);
return chase_symlinks(p, NULL, 0, ret, NULL);
}
int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno) {
......
......@@ -5,7 +5,6 @@
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include "macro.h"
......
......@@ -7,7 +7,6 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "escape.h"
......@@ -750,7 +749,7 @@ static void advance_offsets(
}
char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
const char *i, *begin = NULL;
const char *begin = NULL;
enum {
STATE_OTHER,
STATE_ESCAPE,
......@@ -758,7 +757,7 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
STATE_CSO,
} state = STATE_OTHER;
char *obuf = NULL;
size_t osz = 0, isz, shift[2] = {};
size_t osz = 0, isz, shift[2] = {}, n_carriage_returns = 0;
FILE *f;
assert(ibuf);
......@@ -769,6 +768,8 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
* 1. Replaces TABs by 8 spaces
* 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
* 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
* 4. Strip trailing \r characters (since they would "move the cursor", but have no
* other effect).
*
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
* are any other special characters. Truncated ANSI sequences are left-as is too. This call is
......@@ -784,14 +785,24 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
if (!f)
return NULL;
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
for (const char *i = *ibuf; i < *ibuf + isz + 1; i++) {
switch (state) {
case STATE_OTHER:
if (i >= *ibuf + isz) /* EOT */
break;
else if (*i == '\x1B')
if (*i == '\r') {
n_carriage_returns++;
break;
} else if (*i == '\n')
/* Ignore carriage returns before new line */
n_carriage_returns = 0;
for (; n_carriage_returns > 0; n_carriage_returns--)
fputc('\r', f);