Browse Source

util-linux package update

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 6 years ago
parent
commit
5b1f3c0b44
  1. 44
      SOURCES/0150-lsns-missing-ns-name-is-not-error.patch
  2. 81
      SOURCES/0151-lsns-Fix-parser-for-proc-pid-stat-which-is-including.patch
  3. 757
      SOURCES/0152-libsmartcols-add-basic-tools-necessary-for-new-versi.patch
  4. 6320
      SOURCES/0153-libsmartcols-backport-upstream-version-v2.32-158-gc0.patch
  5. 990
      SOURCES/0154-tests-backport-libsmartcols-tests.patch
  6. 114
      SOURCES/0155-lslogins-fix-password-verification.patch
  7. 53
      SOURCES/0156-umount-add-note-about-lazy.patch
  8. 31
      SOURCES/0157-losetup-add-info-about-lazy-detach-to-manpage.patch
  9. 44
      SOURCES/0158-setarch-Fix-ppc64le-architectures.patch
  10. 717
      SOURCES/0159-fallocate-backport-v2.32-164-g641af90dc.patch
  11. 54
      SOURCES/0160-libmount-fix-mnt_table_is_fs_mounted-for-rbind.patch
  12. 54
      SOURCES/0161-mount-add-ext4-to-some-places-in-man-page.patch
  13. 72
      SOURCES/0162-agetty-keep-c_iflags-unmodified-on-autologin.patch
  14. 73
      SOURCES/0163-sulogin-don-t-use-strcpy-enlarge-pwd-line-buffer.patch
  15. 175
      SOURCES/0164-sulogin-improve-support-for-locked-root-account.patch
  16. 34
      SOURCES/0165-sulogin-Always-make-echo-work-after-performing-getpa.patch
  17. 35
      SOURCES/0166-sulogin-make-getpasswd-.-return-NULL-on-D.patch
  18. 38
      SOURCES/0167-sulogin-bail-out-from-getpasswd-.-on-timeout.patch
  19. 40
      SOURCES/0168-losetup-keep-f-and-devname-mutually-exclusive.patch
  20. 83
      SOURCES/0169-lscpu-fix-mzx-min-MHz-reporting.patch
  21. 253
      SOURCES/0170-chcpu-cleanup-return-codes.patch
  22. 79
      SOURCES/0171-chcpu-cleanup-stdout-stderr-usage.patch
  23. 86
      SOURCES/0172-lscpu-chcpu-Avoid-use-of-the-old-CPU-macros.patch
  24. 74
      SOURCES/0173-chcpu-Fix-maximal-number-of-CPUs.patch
  25. 44
      SOURCES/0174-libblkid-minix-Match-minix-superblock-types.patch
  26. 44
      SOURCES/0175-libblkid-minix-Sanity-check-superblock-s_state-for-v.patch
  27. 90
      SOURCES/0176-libblkid-minix-Use-same-checks-for-version-3.patch
  28. 41
      SOURCES/0177-mount-append-inverting-options-for-mount.-type-on-us.patch
  29. 839
      SOURCES/0178-sulogin-backport-RHEL-8-version.patch
  30. 189
      SPECS/util-linux.spec

44
SOURCES/0150-lsns-missing-ns-name-is-not-error.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
From 8694f63002c6b765e72c36fbf8ed46164d5303e5 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 15 Aug 2016 11:02:18 +0200
Subject: [PATCH 150/173] lsns: missing ns/<name> is not error
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

For example user namespace is optional it does not make sense to
ignore process completely if the ns/user file is missing.

Reported-by: Michał Bartoszkiewicz <mbartoszkiewicz@gmail.com>
Upstream: http://github.com/karelzak/util-linux/commit/3082f8518f2739e9f68e660f1749acdd2b9d7a97
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1543428
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lsns.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c
index fb53a16a4..b8841b7a3 100644
--- a/sys-utils/lsns.c
+++ b/sys-utils/lsns.c
@@ -204,7 +204,7 @@ static inline const struct colinfo *get_column_info(unsigned num)
return &infos[ get_column_id(num) ];
}
-static ino_t get_ns_ino(int dir, const char *nsname, ino_t *ino)
+static int get_ns_ino(int dir, const char *nsname, ino_t *ino)
{
struct stat st;
char path[16];
@@ -269,7 +269,7 @@ static int read_process(struct lsns *ls, pid_t pid)
continue;
rc = get_ns_ino(dirfd(dir), ns_names[i], &p->ns_ids[i]);
- if (rc && rc != -EACCES)
+ if (rc && rc != -EACCES && rc != -ENOENT)
goto done;
rc = 0;
}
--
2.14.4

81
SOURCES/0151-lsns-Fix-parser-for-proc-pid-stat-which-is-including.patch

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
From 7a151a3d74b2972410103b684803e6d6b8fda15b Mon Sep 17 00:00:00 2001
From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Date: Wed, 23 Nov 2016 14:13:34 +0900
Subject: [PATCH 151/173] lsns: Fix parser for /proc/<pid>/stat which is
including space in comm

For example, child process of spamd has

32031 (spamd child) S 32026 32026 32026 0 -1 4210752 338 0 0 0 ...

fscanf("%d %*s %c %d*[^\n]") in read_process() can't parse above as we
expected, because %s only skips non-whitespace. I.e. it parses like
following,

32031 (spamd child) S 32026 32026 32026 0 -1 4210752 338 0 0 0 ...
+---+ +----+ +
%d %*s %c

and returns 2 (pid=32031, state=c).

This fixes it by skipping task->comm part manually.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1543428
Upstream: http://github.com/karelzak/util-linux/commit/3fcbd7978980dc1a29c626b701333e27599e506d
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
---
sys-utils/lsns.c | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c
index b8841b7a3..d32756508 100644
--- a/sys-utils/lsns.c
+++ b/sys-utils/lsns.c
@@ -217,6 +217,30 @@ static int get_ns_ino(int dir, const char *nsname, ino_t *ino)
return 0;
}
+static int parse_proc_stat(FILE *fp, pid_t *pid, char *state, pid_t *ppid)
+{
+ char *line = NULL, *p;
+ size_t len = 0;
+ int rc;
+
+ if (getline(&line, &len, fp) < 0) {
+ rc = -errno;
+ goto error;
+ }
+
+ p = strrchr(line, ')');
+ if (p == NULL ||
+ sscanf(line, "%d (", pid) != 1 ||
+ sscanf(p, ") %c %d*[^\n]", state, ppid) != 2) {
+ rc = -EINVAL;
+ goto error;
+ }
+ rc = 0;
+
+error:
+ free(line);
+ return rc;
+}
static int read_process(struct lsns *ls, pid_t pid)
{
@@ -255,11 +279,9 @@ static int read_process(struct lsns *ls, pid_t pid)
rc = -errno;
goto done;
}
- rc = fscanf(f, "%d %*s %c %d*[^\n]", &p->pid, &p->state, &p->ppid);
- if (rc != 3) {
- rc = rc < 0 ? -errno : -EINVAL;
+ rc = parse_proc_stat(f, &p->pid, &p->state, &p->ppid);
+ if (rc < 0)
goto done;
- }
rc = 0;
for (i = 0; i < ARRAY_SIZE(p->ns_ids); i++) {
--
2.14.4

757
SOURCES/0152-libsmartcols-add-basic-tools-necessary-for-new-versi.patch

@ -0,0 +1,757 @@ @@ -0,0 +1,757 @@
From c465ce9765273e8e1227b192e1917826ac4eaaf7 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 31 May 2018 11:13:31 +0200
Subject: [PATCH 152/173] libsmartcols: add basic tools necessary for new
version

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1561350
Signed-off-by: Karel Zak <kzak@redhat.com>
---
configure.ac | 3 +
include/carefulputc.h | 96 +++++++++++++++++++++++++++-
include/colors.h | 5 ++
include/mbsalign.h | 9 ++-
include/strutils.h | 13 ++--
include/ttyutils.h | 1 +
lib/Makemodule.am | 1 +
lib/color-names.c | 57 +++++++++++++++++
lib/mbsalign.c | 172 +++++++++++++++++++++++++++++++++++++++++---------
lib/ttyutils.c | 52 +++++++++++++++
libfdisk/src/ask.c | 4 +-
11 files changed, 373 insertions(+), 40 deletions(-)
create mode 100644 lib/color-names.c

diff --git a/configure.ac b/configure.ac
index d561e01d0..8cf317dc0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -133,6 +133,9 @@ AC_SUBST([BSD_WARN_CFLAGS])
dnl libtool-2
LT_INIT
+dnl check supported linker flags
+AX_CHECK_VSCRIPT
+
m4_ifndef([PKG_PROG_PKG_CONFIG],
[m4_fatal([Could not locate the pkg-config autoconf
macros. These are usually located in /usr/share/aclocal/pkg.m4.
diff --git a/include/carefulputc.h b/include/carefulputc.h
index a54498cfd..613d94c1e 100644
--- a/include/carefulputc.h
+++ b/include/carefulputc.h
@@ -26,7 +26,87 @@ static inline int carefulputc(int c, FILE *fp) {
return (ret < 0) ? EOF : 0;
}
-static inline void fputs_quoted(const char *data, FILE *out)
+/*
+ * Backported for RHEL7.6 libsmartcols
+ */
+
+/*
+ * Requirements enumerated via testing (V8, Firefox, IE11):
+ *
+ * var charsToEscape = [];
+ * for (var i = 0; i < 65535; i += 1) {
+ * try {
+ * JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
+ * } catch (e) {
+ * charsToEscape.push(i);
+ * }
+ * }
+ */
+static inline void fputs_quoted_case_json(const char *data, FILE *out, int dir)
+{
+ const char *p;
+
+ fputc('"', out);
+ for (p = data; p && *p; p++) {
+
+ const unsigned char c = (unsigned char) *p;
+
+ /* From http://www.json.org
+ *
+ * The double-quote and backslashes would break out a string or
+ * init an escape sequence if not escaped.
+ *
+ * Note that single-quotes and forward slashes, while they're
+ * in the JSON spec, don't break double-quoted strings.
+ */
+ if (c == '"' || c == '\\') {
+ fputc('\\', out);
+ fputc(c, out);
+ continue;
+ }
+
+ /* All non-control characters OK; do the case swap as required. */
+ if (c >= 0x20) {
+ fputc(dir == 1 ? toupper(c) :
+ dir == -1 ? tolower(c) : *p, out);
+ continue;
+ }
+
+ /* In addition, all chars under ' ' break Node's/V8/Chrome's, and
+ * Firefox's JSON.parse function
+ */
+ switch (c) {
+ /* Handle short-hand cases to reduce output size. C
+ * has most of the same stuff here, so if there's an
+ * "Escape for C" function somewhere in the STL, we
+ * should probably be using it.
+ */
+ case '\b':
+ fputs("\\b", out);
+ break;
+ case '\t':
+ fputs("\\t", out);
+ break;
+ case '\n':
+ fputs("\\n", out);
+ break;
+ case '\f':
+ fputs("\\f", out);
+ break;
+ case '\r':
+ fputs("\\r", out);
+ break;
+ default:
+ /* Other assorted control characters */
+ fprintf(out, "\\u00%02x", c);
+ break;
+ }
+ }
+ fputc('"', out);
+}
+
+
+static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
{
const char *p;
@@ -34,16 +114,28 @@ static inline void fputs_quoted(const char *data, FILE *out)
for (p = data; p && *p; p++) {
if ((unsigned char) *p == 0x22 || /* " */
(unsigned char) *p == 0x5c || /* \ */
+ (unsigned char) *p == 0x60 || /* ` */
+ (unsigned char) *p == 0x24 || /* $ */
!isprint((unsigned char) *p) ||
iscntrl((unsigned char) *p)) {
fprintf(out, "\\x%02x", (unsigned char) *p);
} else
- fputc(*p, out);
+ fputc(dir == 1 ? toupper(*p) :
+ dir == -1 ? tolower(*p) :
+ *p, out);
}
fputc('"', out);
}
+#define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0)
+#define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1)
+#define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1)
+
+#define fputs_quoted_json(_d, _o) fputs_quoted_case_json(_d, _o, 0)
+#define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1)
+#define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1)
+
static inline void fputs_nonblank(const char *data, FILE *out)
{
const char *p;
diff --git a/include/colors.h b/include/colors.h
index dd77bf6df..39c0edf46 100644
--- a/include/colors.h
+++ b/include/colors.h
@@ -38,6 +38,11 @@
#define UL_COLOR_WHITE "\033[1;37m"
+/* maximal length of human readable name of ESC seq. */
+#define UL_COLORNAME_MAXSZ 32
+
+extern const char *color_sequence_from_colorname(const char *str);
+
/* Initialize the global variable OUT_IS_TERM */
extern int colors_init(void);
diff --git a/include/mbsalign.h b/include/mbsalign.h
index 5eaf606e5..0c28e6f69 100644
--- a/include/mbsalign.h
+++ b/include/mbsalign.h
@@ -46,11 +46,18 @@ extern size_t mbsalign (const char *src, char *dest,
size_t dest_size, size_t *width,
mbs_align_t align, int flags);
+extern size_t mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
+ size_t *width, mbs_align_t align, int flags,
+ int padchar);
+
extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz);
extern size_t mbs_safe_width(const char *s);
extern char *mbs_safe_encode(const char *s, size_t *width);
-extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf);
+extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars);
extern size_t mbs_safe_encode_size(size_t bytes);
+extern char *mbs_invalid_encode(const char *s, size_t *width);
+extern char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf);
+
#endif /* UTIL_LINUX_MBSALIGN_H */
diff --git a/include/strutils.h b/include/strutils.h
index 1f028e4ed..822fb7d49 100644
--- a/include/strutils.h
+++ b/include/strutils.h
@@ -6,6 +6,7 @@
#include <string.h>
#include <sys/types.h>
#include <stdio.h>
+#include <errno.h>
/* default strtoxx_or_err() exit code */
#ifndef STRTOXX_EXIT_CODE
@@ -57,20 +58,24 @@ static inline void xstrncpy(char *dest, const char *src, size_t n)
dest[n-1] = 0;
}
-static inline char *strdup_to_offset(void *stru, size_t offset, const char *str)
+static inline int strdup_to_offset(void *stru, size_t offset, const char *str)
{
char *n = NULL;
- char **o = (char **) ((char *) stru + offset);
+ char **o;
+ if (!stru)
+ return -EINVAL;
+
+ o = (char **) ((char *) stru + offset);
if (str) {
n = strdup(str);
if (!n)
- return NULL;
+ return -ENOMEM;
}
free(*o);
*o = n;
- return n;
+ return 0;
}
#define strdup_to_struct_member(_s, _m, _str) \
diff --git a/include/ttyutils.h b/include/ttyutils.h
index 13495ba96..47fe34472 100644
--- a/include/ttyutils.h
+++ b/include/ttyutils.h
@@ -47,6 +47,7 @@ struct chardata {
(ptr)->capslock = 0; \
} while (0)
+extern int get_terminal_dimension(int *cols, int *lines);
extern int get_terminal_width(void);
extern int get_terminal_name(int fd, const char **path, const char **name,
const char **number);
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index acae27afb..714233c40 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -6,6 +6,7 @@ libcommon_la_SOURCES = \
lib/blkdev.c \
lib/canonicalize.c \
lib/colors.c \
+ lib/color-names.c \
lib/crc32.c \
lib/env.c \
lib/idcache.c \
diff --git a/lib/color-names.c b/lib/color-names.c
new file mode 100644
index 000000000..cf37670a9
--- /dev/null
+++ b/lib/color-names.c
@@ -0,0 +1,57 @@
+
+#include "c.h"
+#include "colors.h"
+
+struct ul_color_name {
+ const char *name;
+ const char *seq;
+};
+
+/*
+ * qsort/bsearch buddy
+ */
+static int cmp_color_name(const void *a0, const void *b0)
+{
+ struct ul_color_name *a = (struct ul_color_name *) a0,
+ *b = (struct ul_color_name *) b0;
+ return strcmp(a->name, b->name);
+}
+
+/*
+ * Maintains human readable color names
+ */
+const char *color_sequence_from_colorname(const char *str)
+{
+ static const struct ul_color_name basic_schemes[] = {
+ { "black", UL_COLOR_BLACK },
+ { "blink", UL_COLOR_BLINK },
+ { "blue", UL_COLOR_BLUE },
+ { "bold", UL_COLOR_BOLD },
+ { "brown", UL_COLOR_BROWN },
+ { "cyan", UL_COLOR_CYAN },
+ { "darkgray", UL_COLOR_DARK_GRAY },
+ { "gray", UL_COLOR_GRAY },
+ { "green", UL_COLOR_GREEN },
+ { "halfbright", UL_COLOR_HALFBRIGHT },
+ { "lightblue", UL_COLOR_BOLD_BLUE },
+ { "lightcyan", UL_COLOR_BOLD_CYAN },
+ { "lightgray,", UL_COLOR_GRAY },
+ { "lightgreen", UL_COLOR_BOLD_GREEN },
+ { "lightmagenta", UL_COLOR_BOLD_MAGENTA },
+ { "lightred", UL_COLOR_BOLD_RED },
+ { "magenta", UL_COLOR_MAGENTA },
+ { "red", UL_COLOR_RED },
+ { "reset", UL_COLOR_RESET, },
+ { "reverse", UL_COLOR_REVERSE },
+ { "yellow", UL_COLOR_BOLD_YELLOW },
+ };
+ struct ul_color_name key = { .name = (char *) str }, *res;
+
+ if (!str)
+ return NULL;
+
+ res = bsearch(&key, basic_schemes, ARRAY_SIZE(basic_schemes),
+ sizeof(struct ul_color_name),
+ cmp_color_name);
+ return res ? res->seq : NULL;
+}
diff --git a/lib/mbsalign.c b/lib/mbsalign.c
index b307d19f7..8fdab9ee9 100644
--- a/lib/mbsalign.c
+++ b/lib/mbsalign.c
@@ -27,9 +27,9 @@
#include "c.h"
#include "mbsalign.h"
+#include "strutils.h"
#include "widechar.h"
-#ifdef HAVE_WIDECHAR
/* Replace non printable chars.
Note \t and \n etc. are non printable.
Return 1 if replacement made, 0 otherwise. */
@@ -43,17 +43,19 @@
*/
size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz)
{
- mbstate_t st;
const char *p = buf, *last = buf;
size_t width = 0, bytes = 0;
+#ifdef HAVE_WIDECHAR
+ mbstate_t st;
memset(&st, 0, sizeof(st));
-
+#endif
if (p && *p && bufsz)
last = p + (bufsz - 1);
while (p && *p && p <= last) {
- if (iscntrl((unsigned char) *p)) {
+ if ((p < last && *p == '\\' && *(p + 1) == 'x')
+ || iscntrl((unsigned char) *p)) {
width += 4, bytes += 4; /* *p encoded to \x?? */
p++;
}
@@ -106,28 +108,36 @@ size_t mbs_safe_width(const char *s)
/*
* Copy @s to @buf and replace control and non-printable chars with
- * \x?? hex sequence. The @width returns number of cells.
+ * \x?? hex sequence. The @width returns number of cells. The @safechars
+ * are not encoded.
*
* The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
* bytes.
*/
-char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
+char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const char *safechars)
{
- mbstate_t st;
const char *p = s;
char *r;
size_t sz = s ? strlen(s) : 0;
+#ifdef HAVE_WIDECHAR
+ mbstate_t st;
+ memset(&st, 0, sizeof(st));
+#endif
if (!sz || !buf)
return NULL;
- memset(&st, 0, sizeof(st));
-
r = buf;
*width = 0;
while (p && *p) {
- if (iscntrl((unsigned char) *p)) {
+ if (safechars && strchr(safechars, *p)) {
+ *r++ = *p++;
+ continue;
+ }
+
+ if ((*p == '\\' && *(p + 1) == 'x')
+ || iscntrl((unsigned char) *p)) {
sprintf(r, "\\x%02x", (unsigned char) *p);
r += 4;
*width += 4;
@@ -152,13 +162,13 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
r += 4;
*width += 4;
} else {
- width++;
+ (*width)++;
*r++ = *p;
}
} else if (!iswprint(wc)) {
size_t i;
for (i = 0; i < len; i++) {
- sprintf(r, "\\x%02x", (unsigned char) *p);
+ sprintf(r, "\\x%02x", (unsigned char) p[i]);
r += 4;
*width += 4;
}
@@ -177,13 +187,76 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf)
*width += 4;
} else {
*r++ = *p++;
- *width++;
+ (*width)++;
}
#endif
}
*r = '\0';
+ return buf;
+}
+/*
+ * Copy @s to @buf and replace broken sequences to \x?? hex sequence. The
+ * @width returns number of cells. The @safechars are not encoded.
+ *
+ * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s)))
+ * bytes.
+ */
+char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf)
+{
+ const char *p = s;
+ char *r;
+ size_t sz = s ? strlen(s) : 0;
+
+#ifdef HAVE_WIDECHAR
+ mbstate_t st;
+ memset(&st, 0, sizeof(st));
+#endif
+ if (!sz || !buf)
+ return NULL;
+
+ r = buf;
+ *width = 0;
+
+ while (p && *p) {
+#ifdef HAVE_WIDECHAR
+ wchar_t wc;
+ size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st);
+#else
+ size_t len = 1;
+#endif
+
+ if (len == 0)
+ break; /* end of string */
+
+ if (len == (size_t) -1 || len == (size_t) -2) {
+ len = 1;
+ /*
+ * Not valid multibyte sequence -- maybe it's
+ * printable char according to the current locales.
+ */
+ if (!isprint((unsigned char) *p)) {
+ sprintf(r, "\\x%02x", (unsigned char) *p);
+ r += 4;
+ *width += 4;
+ } else {
+ (*width)++;
+ *r++ = *p;
+ }
+ } else if (*p == '\\' && *(p + 1) == 'x') {
+ sprintf(r, "\\x%02x", (unsigned char) *p);
+ r += 4;
+ *width += 4;
+ } else {
+ memcpy(r, p, len);
+ r += len;
+ *width += wcwidth(wc);
+ }
+ p += len;
+ }
+
+ *r = '\0';
return buf;
}
@@ -199,17 +272,39 @@ size_t mbs_safe_encode_size(size_t bytes)
char *mbs_safe_encode(const char *s, size_t *width)
{
size_t sz = s ? strlen(s) : 0;
- char *buf;
+ char *buf, *ret = NULL;
if (!sz)
return NULL;
buf = malloc(mbs_safe_encode_size(sz));
- if (!buf)
- return NULL;
+ if (buf)
+ ret = mbs_safe_encode_to_buffer(s, width, buf, NULL);
+ if (!ret)
+ free(buf);
+ return ret;
+}
- return mbs_safe_encode_to_buffer(s, width, buf);
+/*
+ * Returns allocated string where all broken widechars chars are
+ * replaced with \x?? hex sequence.
+ */
+char *mbs_invalid_encode(const char *s, size_t *width)
+{
+ size_t sz = s ? strlen(s) : 0;
+ char *buf, *ret = NULL;
+
+ if (!sz)
+ return NULL;
+ buf = malloc(mbs_safe_encode_size(sz));
+ if (buf)
+ ret = mbs_invalid_encode_to_buffer(s, width, buf);
+ if (!ret)
+ free(buf);
+ return ret;
}
+#ifdef HAVE_WIDECHAR
+
static bool
wc_ensure_printable (wchar_t *wchars)
{
@@ -246,6 +341,7 @@ wc_truncate (wchar_t *wc, size_t width)
}
if (cells + next_cells > width)
break;
+
cells += next_cells;
wc++;
}
@@ -273,7 +369,7 @@ rpl_wcswidth (const wchar_t *s, size_t n)
return ret;
}
-#endif
+#endif /* HAVE_WIDECHAR */
/* Truncate multi-byte string to @width and returns number of
* bytes of the new string @str, and in @width returns number
@@ -290,7 +386,7 @@ mbs_truncate(char *str, size_t *width)
if (sz == (ssize_t) -1)
goto done;
- wcs = malloc((sz + 1) * sizeof(wchar_t));
+ wcs = calloc(1, (sz + 1) * sizeof(wchar_t));
if (!wcs)
goto done;
@@ -301,7 +397,7 @@ mbs_truncate(char *str, size_t *width)
done:
free(wcs);
#else
- if (*width < bytes)
+ if (bytes >= 0 && *width < (size_t) bytes)
bytes = *width;
#endif
if (bytes >= 0)
@@ -315,16 +411,23 @@ done:
A pointer to the terminating NUL is returned. */
static char*
-mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
+mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces, int padchar)
{
/* FIXME: Should we pad with "figure space" (\u2007)
if non ascii data present? */
- while (n_spaces-- && (dest < dest_end))
- *dest++ = ' ';
+ for (/* nothing */; n_spaces && (dest < dest_end); n_spaces--)
+ *dest++ = padchar;
*dest = '\0';
return dest;
}
+size_t
+mbsalign (const char *src, char *dest, size_t dest_size,
+ size_t *width, mbs_align_t align, int flags)
+{
+ return mbsalign_with_padding(src, dest, dest_size, width, align, flags, ' ');
+}
+
/* Align a string, SRC, in a field of *WIDTH columns, handling multi-byte
characters; write the result into the DEST_SIZE-byte buffer, DEST.
ALIGNMENT specifies whether to left- or right-justify or to center.
@@ -339,8 +442,14 @@ mbs_align_pad (char *dest, const char* dest_end, size_t n_spaces)
Update *WIDTH to indicate how many columns were used before padding. */
size_t
-mbsalign (const char *src, char *dest, size_t dest_size,
- size_t *width, mbs_align_t align, int flags)
+mbsalign_with_padding (const char *src, char *dest, size_t dest_size,
+ size_t *width, mbs_align_t align,
+#ifdef HAVE_WIDECHAR
+ int flags,
+#else
+ int flags __attribute__((__unused__)),
+#endif
+ int padchar)
{
size_t ret = -1;
size_t src_size = strlen (src) + 1;
@@ -350,10 +459,11 @@ mbsalign (const char *src, char *dest, size_t dest_size,
size_t n_cols = src_size - 1;
size_t n_used_bytes = n_cols; /* Not including NUL */
size_t n_spaces = 0, space_left;
+
+#ifdef HAVE_WIDECHAR
bool conversion = false;
bool wc_enabled = false;
-#ifdef HAVE_WIDECHAR
/* In multi-byte locales convert to wide characters
to allow easy truncation. Also determine number
of screen columns used. */
@@ -407,9 +517,9 @@ mbsalign (const char *src, char *dest, size_t dest_size,
n_cols = wc_truncate (str_wc, *width);
n_used_bytes = wcstombs (newstr, str_wc, src_size);
}
-#endif
mbsalign_unibyte:
+#endif
if (n_cols > *width) /* Unibyte truncation required. */
{
@@ -451,14 +561,14 @@ mbsalign_unibyte:
abort();
}
- dest = mbs_align_pad (dest, dest_end, start_spaces);
+ dest = mbs_align_pad (dest, dest_end, start_spaces, padchar);
space_left = dest_end - dest;
dest = mempcpy (dest, str_to_print, min (n_used_bytes, space_left));
- mbs_align_pad (dest, dest_end, end_spaces);
+ mbs_align_pad (dest, dest_end, end_spaces, padchar);
}
-
+#ifdef HAVE_WIDECHAR
mbsalign_cleanup:
-
+#endif
free (str_wc);
free (newstr);
diff --git a/lib/ttyutils.c b/lib/ttyutils.c
index ea551e26c..91497e763 100644
--- a/lib/ttyutils.c
+++ b/lib/ttyutils.c
@@ -9,6 +9,58 @@
#include "c.h"
#include "ttyutils.h"
+/*
+ * Backported for RHEL7.6 libsmartcols
+ */
+static int get_env_int(const char *name)
+{
+ const char *cp = getenv(name);
+
+ if (cp) {
+ char *end = NULL;
+ long x;
+
+ errno = 0;
+ x = strtol(cp, &end, 10);
+
+ if (errno == 0 && end && *end == '\0' && end > cp &&
+ x > 0 && x <= INT_MAX)
+ return x;
+ }
+
+ return -1;
+}
+
+int get_terminal_dimension(int *cols, int *lines)
+{
+ int c = 0, l = 0;
+
+#if defined(TIOCGWINSZ)
+ struct winsize w_win;
+ if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &w_win) == 0) {
+ c = w_win.ws_col;
+ l = w_win.ws_row;
+ }
+#elif defined(TIOCGSIZE)
+ struct ttysize t_win;
+ if (ioctl (STDOUT_FILENO, TIOCGSIZE, &t_win) == 0) {
+ c = t_win.ts_cols;
+ l = t_win.ts_lines;
+ }
+#endif
+
+ if (cols && c <= 0)
+ c = get_env_int("COLUMNS");
+ if (lines && l <= 0)
+ l = get_env_int("LINES");
+
+ if (cols)
+ *cols = c;
+ if (lines)
+ *lines = l;
+ return 0;
+}
+
int get_terminal_width(void)
{
#ifdef TIOCGSIZE
diff --git a/libfdisk/src/ask.c b/libfdisk/src/ask.c
index cdb4d0124..a10f3dc82 100644
--- a/libfdisk/src/ask.c
+++ b/libfdisk/src/ask.c
@@ -42,7 +42,7 @@ const char *fdisk_ask_get_query(struct fdisk_ask *ask)
int fdisk_ask_set_query(struct fdisk_ask *ask, const char *str)
{
assert(ask);
- return !strdup_to_struct_member(ask, query, str) ? -ENOMEM : 0;
+ return strdup_to_struct_member(ask, query, str);
}
int fdisk_ask_get_type(struct fdisk_ask *ask)
@@ -90,7 +90,7 @@ const char *fdisk_ask_number_get_range(struct fdisk_ask *ask)
int fdisk_ask_number_set_range(struct fdisk_ask *ask, const char *range)
{
assert(ask);
- return !strdup_to_struct_member(ask, data.num.range, range) ? -ENOMEM : 0;
+ return strdup_to_struct_member(ask, data.num.range, range);
}
uint64_t fdisk_ask_number_get_default(struct fdisk_ask *ask)
--
2.14.4

6320
SOURCES/0153-libsmartcols-backport-upstream-version-v2.32-158-gc0.patch

File diff suppressed because it is too large Load Diff

990
SOURCES/0154-tests-backport-libsmartcols-tests.patch

@ -0,0 +1,990 @@ @@ -0,0 +1,990 @@
From 83f79678dbb9cb48969968fa4df57d98c67a321d Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 31 May 2018 11:44:35 +0200
Subject: [PATCH 154/173] tests: backport libsmartcols tests

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1561350
Signed-off-by: Karel Zak <kzak@redhat.com>
---
tests/commands.sh | 2 +
tests/expected/libsmartcols/fromfile | 1 +
.../libsmartcols/fromfile-column-separator | 11 +
tests/expected/libsmartcols/fromfile-export | 10 +
tests/expected/libsmartcols/fromfile-hidden | 11 +
tests/expected/libsmartcols/fromfile-noextremes | 12 ++
tests/expected/libsmartcols/fromfile-raw | 11 +
tests/expected/libsmartcols/fromfile-right | 11 +
tests/expected/libsmartcols/fromfile-right-maxout | 11 +
tests/expected/libsmartcols/fromfile-strictwidth | 11 +
tests/expected/libsmartcols/fromfile-tree | 11 +
tests/expected/libsmartcols/fromfile-tree-end | 11 +
tests/expected/libsmartcols/fromfile-tree-json | 29 +++
tests/expected/libsmartcols/fromfile-tree-middle | 11 +
tests/expected/libsmartcols/fromfile-trunc | 11 +
tests/expected/libsmartcols/fromfile-wrap | 17 ++
tests/expected/libsmartcols/fromfile-wrap-tree | 18 ++
tests/expected/libsmartcols/fromfile-wrapnl | 19 ++
tests/expected/libsmartcols/fromfile-wrapnl-tree | 19 ++
tests/expected/libsmartcols/title | 16 ++
tests/ts/libsmartcols/files/col-hidden | 3 +
tests/ts/libsmartcols/files/col-id | 3 +
tests/ts/libsmartcols/files/col-name | 3 +
tests/ts/libsmartcols/files/col-noextremes | 3 +
tests/ts/libsmartcols/files/col-number | 3 +
tests/ts/libsmartcols/files/col-parent | 3 +
tests/ts/libsmartcols/files/col-strict | 3 +
tests/ts/libsmartcols/files/col-string | 3 +
tests/ts/libsmartcols/files/col-tree | 3 +
tests/ts/libsmartcols/files/col-trunc | 3 +
tests/ts/libsmartcols/files/col-wrap | 3 +
tests/ts/libsmartcols/files/col-wrapnl | 3 +
tests/ts/libsmartcols/files/data-id | 10 +
tests/ts/libsmartcols/files/data-number | 10 +
tests/ts/libsmartcols/files/data-number-tiny | 10 +
tests/ts/libsmartcols/files/data-parent | 10 +
tests/ts/libsmartcols/files/data-string | 10 +
tests/ts/libsmartcols/files/data-string-extreme | 10 +
tests/ts/libsmartcols/files/data-string-long | 10 +
tests/ts/libsmartcols/files/data-string-nl | 10 +
tests/ts/libsmartcols/fromfile | 240 +++++++++++++++++++++
tests/ts/libsmartcols/title | 28 +++
42 files changed, 637 insertions(+)
create mode 100644 tests/expected/libsmartcols/fromfile
create mode 100644 tests/expected/libsmartcols/fromfile-column-separator
create mode 100644 tests/expected/libsmartcols/fromfile-export
create mode 100644 tests/expected/libsmartcols/fromfile-hidden
create mode 100644 tests/expected/libsmartcols/fromfile-noextremes
create mode 100644 tests/expected/libsmartcols/fromfile-raw
create mode 100644 tests/expected/libsmartcols/fromfile-right
create mode 100644 tests/expected/libsmartcols/fromfile-right-maxout
create mode 100644 tests/expected/libsmartcols/fromfile-strictwidth
create mode 100644 tests/expected/libsmartcols/fromfile-tree
create mode 100644 tests/expected/libsmartcols/fromfile-tree-end
create mode 100644 tests/expected/libsmartcols/fromfile-tree-json
create mode 100644 tests/expected/libsmartcols/fromfile-tree-middle
create mode 100644 tests/expected/libsmartcols/fromfile-trunc
create mode 100644 tests/expected/libsmartcols/fromfile-wrap
create mode 100644 tests/expected/libsmartcols/fromfile-wrap-tree
create mode 100644 tests/expected/libsmartcols/fromfile-wrapnl
create mode 100644 tests/expected/libsmartcols/fromfile-wrapnl-tree
create mode 100644 tests/expected/libsmartcols/title
create mode 100644 tests/ts/libsmartcols/files/col-hidden
create mode 100644 tests/ts/libsmartcols/files/col-id
create mode 100644 tests/ts/libsmartcols/files/col-name
create mode 100644 tests/ts/libsmartcols/files/col-noextremes
create mode 100644 tests/ts/libsmartcols/files/col-number
create mode 100644 tests/ts/libsmartcols/files/col-parent
create mode 100644 tests/ts/libsmartcols/files/col-strict
create mode 100644 tests/ts/libsmartcols/files/col-string
create mode 100644 tests/ts/libsmartcols/files/col-tree
create mode 100644 tests/ts/libsmartcols/files/col-trunc
create mode 100644 tests/ts/libsmartcols/files/col-wrap
create mode 100644 tests/ts/libsmartcols/files/col-wrapnl
create mode 100644 tests/ts/libsmartcols/files/data-id
create mode 100644 tests/ts/libsmartcols/files/data-number
create mode 100644 tests/ts/libsmartcols/files/data-number-tiny
create mode 100644 tests/ts/libsmartcols/files/data-parent
create mode 100644 tests/ts/libsmartcols/files/data-string
create mode 100644 tests/ts/libsmartcols/files/data-string-extreme
create mode 100644 tests/ts/libsmartcols/files/data-string-long
create mode 100644 tests/ts/libsmartcols/files/data-string-nl
create mode 100755 tests/ts/libsmartcols/fromfile
create mode 100755 tests/ts/libsmartcols/title

diff --git a/tests/commands.sh b/tests/commands.sh
index e769b5dac..96b8dc97c 100644
--- a/tests/commands.sh
+++ b/tests/commands.sh
@@ -20,6 +20,8 @@ TS_HELPER_PARTITIONS="$top_builddir/sample-partitions"
TS_HELPER_PATHS="$top_builddir/test_pathnames"
TS_HELPER_STRUTILS="$top_builddir/test_strutils"
TS_HELPER_SYSINFO="$top_builddir/test_sysinfo"
+TS_HELPER_LIBSMARTCOLS_FROMFILE="$top_builddir/sample-scols-fromfile"
+TS_HELPER_LIBSMARTCOLS_TITLE="$top_builddir/sample-scols-title"
# paths to commands
TS_CMD_BLKID=${TS_CMD_BLKID-"$top_builddir/blkid"}
diff --git a/tests/expected/libsmartcols/fromfile b/tests/expected/libsmartcols/fromfile
new file mode 100644
index 000000000..4155aa36f
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile
@@ -0,0 +1 @@
+...done.
diff --git a/tests/expected/libsmartcols/fromfile-column-separator b/tests/expected/libsmartcols/fromfile-column-separator
new file mode 100644
index 000000000..8c5aa2aff
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-column-separator
@@ -0,0 +1,11 @@
+NAME | NUM|TRUNC
+aaaa | 0|qqqqqqqqqqqqqqqqqX
+bbb | 100|dddddddddddddX
+ccccc | 21|ffffffffffffffffffffffffffffffffffffffffX
+dddddd| 3|ssssssssssX
+ee | 411|ddddddddddddddddddddddddddX
+ffff | 5111|jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+gggggg|678993321|mmmmmmmmmmmmmmmmmmmX
+hhh | 7666666|lllllllllllllllllllllllllllllllllllllX
+iiiiii| 8765|yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+jj | 987456|pppppppppX
diff --git a/tests/expected/libsmartcols/fromfile-export b/tests/expected/libsmartcols/fromfile-export
new file mode 100644
index 000000000..f63afd882
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-export
@@ -0,0 +1,10 @@
+NAME="aaaa" NUM="0" TRUNC="qqqqqqqqqqqqqqqqqX"
+NAME="bbb" NUM="100" TRUNC="dddddddddddddX"
+NAME="ccccc" NUM="21" TRUNC="ffffffffffffffffffffffffffffffffffffffffX"
+NAME="dddddd" NUM="3" TRUNC="ssssssssssX"
+NAME="ee" NUM="411" TRUNC="ddddddddddddddddddddddddddX"
+NAME="ffff" NUM="5111" TRUNC="jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX"
+NAME="gggggg" NUM="678993321" TRUNC="mmmmmmmmmmmmmmmmmmmX"
+NAME="hhh" NUM="7666666" TRUNC="lllllllllllllllllllllllllllllllllllllX"
+NAME="iiiiii" NUM="8765" TRUNC="yyyyyyyyyyyyyyyyyyyyyyyyyyyyX"
+NAME="jj" NUM="987456" TRUNC="pppppppppX"
diff --git a/tests/expected/libsmartcols/fromfile-hidden b/tests/expected/libsmartcols/fromfile-hidden
new file mode 100644
index 000000000..cf50bcb3e
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-hidden
@@ -0,0 +1,11 @@
+NAME NUM
+aaaa 0
+bbb 100
+ccccc 21
+dddddd 3
+ee 411
+ffff 5111
+gggggg 678993321
+hhh 7666666
+iiiiii 8765
+jj 987456
diff --git a/tests/expected/libsmartcols/fromfile-noextremes b/tests/expected/libsmartcols/fromfile-noextremes
new file mode 100644
index 000000000..4bac08070
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-noextremes
@@ -0,0 +1,12 @@
+NAME NOEXTREME NUM NAME NUM
+aaaa qqqqqqX 0 aaaa 0
+bbb ddddddddX 100 bbb 100
+ccccc ffffffffffffffffffffffffffffffffffX
+ 21 ccccc 21
+dddddd sssX 3 dddddd 3
+ee ddX 411 ee 411
+ffff jjjjjX 5111 ffff 5111
+gggggg mmmmmmmX 678993321 gggggg 678993321
+hhh llllllllllX 7666666 hhh 7666666
+iiiiii yyyyyyX 8765 iiiiii 8765
+jj pppppX 987456 jj 987456
diff --git a/tests/expected/libsmartcols/fromfile-raw b/tests/expected/libsmartcols/fromfile-raw
new file mode 100644
index 000000000..cc188aaab
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-raw
@@ -0,0 +1,11 @@
+NAME NUM TRUNC
+aaaa 0 qqqqqqqqqqqqqqqqqX
+bbb 100 dddddddddddddX
+ccccc 21 ffffffffffffffffffffffffffffffffffffffffX
+dddddd 3 ssssssssssX
+ee 411 ddddddddddddddddddddddddddX
+ffff 5111 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+gggggg 678993321 mmmmmmmmmmmmmmmmmmmX
+hhh 7666666 lllllllllllllllllllllllllllllllllllllX
+iiiiii 8765 yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+jj 987456 pppppppppX
diff --git a/tests/expected/libsmartcols/fromfile-right b/tests/expected/libsmartcols/fromfile-right
new file mode 100644
index 000000000..d78285a13
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-right
@@ -0,0 +1,11 @@
+NAME NUM STRINGS
+aaaa 0 qqqqqqqqqqqqqqqqqX
+bbb 100 dddddddddddddX
+ccccc 21 ffffffffffffffffffffffffffffffffffffffffX
+dddddd 3 ssssssssssX
+ee 411 ddddddddddddddddddddddddddX
+ffff 5111 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+gggggg 678993321 mmmmmmmmmmmmmmmmmmmX
+hhh 7666666 lllllllllllllllllllllllllllllllllllllX
+iiiiii 8765 yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+jj 987456 pppppppppX
diff --git a/tests/expected/libsmartcols/fromfile-right-maxout b/tests/expected/libsmartcols/fromfile-right-maxout
new file mode 100644
index 000000000..3bcb65abd
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-right-maxout
@@ -0,0 +1,11 @@
+NAME NUM
+aaaa 0
+bbb 100
+ccccc 21
+dddddd 3
+ee 411
+ffff 5111
+gggggg 678993321
+hhh 7666666
+iiiiii 8765
+jj 987456
diff --git a/tests/expected/libsmartcols/fromfile-strictwidth b/tests/expected/libsmartcols/fromfile-strictwidth
new file mode 100644
index 000000000..41054b235
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-strictwidth
@@ -0,0 +1,11 @@
+NAME STRICT NUM
+aaaa 0 0
+bbb 1 100
+ccccc 2 21
+dddddd 3 3
+ee 4 411
+ffff 5 5111
+gggggg 6 678993321
+hhh 7 7666666
+iiiiii 8 8765
+jj 9 987456
diff --git a/tests/expected/libsmartcols/fromfile-tree b/tests/expected/libsmartcols/fromfile-tree
new file mode 100644
index 000000000..9d345f8dc
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-tree
@@ -0,0 +1,11 @@
+TREE ID PARENT STRINGS
+aaaa 1 0 qqqqqqqqqqqqqqqqqX
+|-bbb 2 1 dddddddddddddX
+| |-ee 5 2 ddddddddddddddddddddddddddX
+| `-ffff 6 2 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+|-ccccc 3 1 ffffffffffffffffffffffffffffffffffffffffX
+| `-gggggg 7 3 mmmmmmmmmmmmmmmmmmmX
+| |-hhh 8 7 lllllllllllllllllllllllllllllllllllllX
+| | `-iiiiii 9 8 yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+| `-jj 10 7 pppppppppX
+`-dddddd 4 1 ssssssssssX
diff --git a/tests/expected/libsmartcols/fromfile-tree-end b/tests/expected/libsmartcols/fromfile-tree-end
new file mode 100644
index 000000000..41aebff56
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-tree-end
@@ -0,0 +1,11 @@
+ID PARENT STRINGS TREE
+ 1 0 qqqqqqqqqqqqqqqqqX aaaa
+ 2 1 dddddddddddddX |-bbb
+ 5 2 ddddddddddddddddddddddddddX | |-ee
+ 6 2 jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX | `-ffff
+ 3 1 ffffffffffffffffffffffffffffffffffffffffX |-ccccc
+ 7 3 mmmmmmmmmmmmmmmmmmmX | `-gggggg
+ 8 7 lllllllllllllllllllllllllllllllllllllX | |-hhh
+ 9 8 yyyyyyyyyyyyyyyyyyyyyyyyyyyyX | | `-iiiiii
+10 7 pppppppppX | `-jj
+ 4 1 ssssssssssX `-dddddd
diff --git a/tests/expected/libsmartcols/fromfile-tree-json b/tests/expected/libsmartcols/fromfile-tree-json
new file mode 100644
index 000000000..5b3546d0a
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-tree-json
@@ -0,0 +1,29 @@
+{
+ "testtable": [
+ {"tree":"aaaa", "id":"1", "parent":"0", "strings":"qqqqqqqqqqqqqqqqqX",
+ "children": [
+ {"tree":"bbb", "id":"2", "parent":"1", "strings":"dddddddddddddX",
+ "children": [
+ {"tree":"ee", "id":"5", "parent":"2", "strings":"ddddddddddddddddddddddddddX"},
+ {"tree":"ffff", "id":"6", "parent":"2", "strings":"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX"}
+ ]
+ },
+ {"tree":"ccccc", "id":"3", "parent":"1", "strings":"ffffffffffffffffffffffffffffffffffffffffX",
+ "children": [
+ {"tree":"gggggg", "id":"7", "parent":"3", "strings":"mmmmmmmmmmmmmmmmmmmX",
+ "children": [
+ {"tree":"hhh", "id":"8", "parent":"7", "strings":"lllllllllllllllllllllllllllllllllllllX",
+ "children": [
+ {"tree":"iiiiii", "id":"9", "parent":"8", "strings":"yyyyyyyyyyyyyyyyyyyyyyyyyyyyX"}
+ ]
+ },
+ {"tree":"jj", "id":"10", "parent":"7", "strings":"pppppppppX"}
+ ]
+ }
+ ]
+ },
+ {"tree":"dddddd", "id":"4", "parent":"1", "strings":"ssssssssssX"}
+ ]
+ }
+ ]
+}
diff --git a/tests/expected/libsmartcols/fromfile-tree-middle b/tests/expected/libsmartcols/fromfile-tree-middle
new file mode 100644
index 000000000..b2183313c
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-tree-middle
@@ -0,0 +1,11 @@
+ID PARENT TREE STRINGS
+ 1 0 aaaa qqqqqqqqqqqqqqqqqX
+ 2 1 |-bbb dddddddddddddX
+ 5 2 | |-ee ddddddddddddddddddddddddddX
+ 6 2 | `-ffff jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+ 3 1 |-ccccc ffffffffffffffffffffffffffffffffffffffffX
+ 7 3 | `-gggggg mmmmmmmmmmmmmmmmmmmX
+ 8 7 | |-hhh lllllllllllllllllllllllllllllllllllllX
+ 9 8 | | `-iiiiii yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+10 7 | `-jj pppppppppX
+ 4 1 `-dddddd ssssssssssX
diff --git a/tests/expected/libsmartcols/fromfile-trunc b/tests/expected/libsmartcols/fromfile-trunc
new file mode 100644
index 000000000..6a095dc88
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-trunc
@@ -0,0 +1,11 @@
+NAME NUM TRUNC
+aaaa 0 qqqqqqqqqqqqqqqqqX
+bbb 100 dddddddddddddX
+ccccc 21 fffffffffffffffffffffff
+dddddd 3 ssssssssssX
+ee 411 ddddddddddddddddddddddd
+ffff 5111 jjjjjjjjjjjjjjjjjjjjjjj
+gggggg 678993321 mmmmmmmmmmmmmmmmmmmX
+hhh 7666666 lllllllllllllllllllllll
+iiiiii 8765 yyyyyyyyyyyyyyyyyyyyyyy
+jj 987456 pppppppppX
diff --git a/tests/expected/libsmartcols/fromfile-wrap b/tests/expected/libsmartcols/fromfile-wrap
new file mode 100644
index 000000000..bb94f4973
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-wrap
@@ -0,0 +1,17 @@
+NAME NUM WRAP
+aaaa 0 qqqqqqqqqqqqqqqqqX
+bbb 100 dddddddddddddX
+ccccc 21 fffffffffffffffffffffff
+ fffffffffffffffffX
+dddddd 3 ssssssssssX
+ee 411 ddddddddddddddddddddddd
+ dddX
+ffff 5111 jjjjjjjjjjjjjjjjjjjjjjj
+ jjjjjjjjjjjjjjjjjjjjjjj
+ jjjX
+gggggg 678993321 mmmmmmmmmmmmmmmmmmmX
+hhh 7666666 lllllllllllllllllllllll
+ llllllllllllllX
+iiiiii 8765 yyyyyyyyyyyyyyyyyyyyyyy
+ yyyyyX
+jj 987456 pppppppppX
diff --git a/tests/expected/libsmartcols/fromfile-wrap-tree b/tests/expected/libsmartcols/fromfile-wrap-tree
new file mode 100644
index 000000000..a2db7a4ac
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-wrap-tree
@@ -0,0 +1,18 @@
+TREE ID PARENT WRAP
+aaaa 1 0 qqqqqqqqqqqqqqqqqX
+|-bbb 2 1 dddddddddddddX
+| |-ee 5 2 dddddddddddddddddddd
+| | ddddddX
+| `-ffff 6 2 jjjjjjjjjjjjjjjjjjjj
+| jjjjjjjjjjjjjjjjjjjj
+| jjjjjjjjjX
+|-ccccc 3 1 ffffffffffffffffffff
+| | ffffffffffffffffffff
+| | X
+| `-gggggg 7 3 mmmmmmmmmmmmmmmmmmmX
+| |-hhh 8 7 llllllllllllllllllll
+| | | lllllllllllllllllX
+| | `-iiiiii 9 8 yyyyyyyyyyyyyyyyyyyy
+| | yyyyyyyyX
+| `-jj 10 7 pppppppppX
+`-dddddd 4 1 ssssssssssX
diff --git a/tests/expected/libsmartcols/fromfile-wrapnl b/tests/expected/libsmartcols/fromfile-wrapnl
new file mode 100644
index 000000000..c747ebb08
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-wrapnl
@@ -0,0 +1,19 @@
+NAME NUM WRAPNL
+aaaa 0 aaa
+bbb 100 bbbbb
+ccccc 21 cccc
+ CCCC
+dddddd 3 dddddddd
+ DDDD
+ DD
+ee 411 hello
+ baby
+ffff 5111 aaa
+ bbb
+ ccc
+ ddd
+gggggg 678993321 eee
+hhh 7666666 fffff
+iiiiii 8765 g
+ hhhhh
+jj 987456 ppppppppp
diff --git a/tests/expected/libsmartcols/fromfile-wrapnl-tree b/tests/expected/libsmartcols/fromfile-wrapnl-tree
new file mode 100644
index 000000000..3862cf16a
--- /dev/null
+++ b/tests/expected/libsmartcols/fromfile-wrapnl-tree
@@ -0,0 +1,19 @@
+TREE ID PARENT WRAPNL
+aaaa 1 0 aaa
+|-bbb 2 1 bbbbb
+| |-ee 5 2 hello
+| | baby
+| `-ffff 6 2 aaa
+| bbb
+| ccc
+| ddd
+|-ccccc 3 1 cccc
+| | CCCC
+| `-gggggg 7 3 eee
+| |-hhh 8 7 fffff
+| | `-iiiiii 9 8 g
+| | hhhhh
+| `-jj 10 7 ppppppppp
+`-dddddd 4 1 dddddddd
+ DDDD
+ DD
diff --git a/tests/expected/libsmartcols/title b/tests/expected/libsmartcols/title
new file mode 100644
index 000000000..bb5d7225a
--- /dev/null
+++ b/tests/expected/libsmartcols/title
@@ -0,0 +1,16 @@
+ This is right title
+NAME DATA
+foo bla bla bla
+bar alb alb alb
+This is left title (without padding)
+NAME DATA
+foo bla bla bla
+bar alb alb alb
+=======================This is center title (with padding)======================
+NAME DATA
+foo bla bla bla
+bar alb alb alb
+This is left title (with padding)-----------------------------------------------
+NAME DATA
+foo bla bla bla
+bar alb alb alb
diff --git a/tests/ts/libsmartcols/files/col-hidden b/tests/ts/libsmartcols/files/col-hidden
new file mode 100644
index 000000000..83182a8ee
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-hidden
@@ -0,0 +1,3 @@
+FOO
+0
+hidden
diff --git a/tests/ts/libsmartcols/files/col-id b/tests/ts/libsmartcols/files/col-id
new file mode 100644
index 000000000..0188f42a0
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-id
@@ -0,0 +1,3 @@
+ID
+0
+right
diff --git a/tests/ts/libsmartcols/files/col-name b/tests/ts/libsmartcols/files/col-name
new file mode 100644
index 000000000..0a98f29cf
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-name
@@ -0,0 +1,3 @@
+NAME
+0
+none
diff --git a/tests/ts/libsmartcols/files/col-noextremes b/tests/ts/libsmartcols/files/col-noextremes
new file mode 100644
index 000000000..715edce7e
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-noextremes
@@ -0,0 +1,3 @@
+NOEXTREME
+0
+noextremes
diff --git a/tests/ts/libsmartcols/files/col-number b/tests/ts/libsmartcols/files/col-number
new file mode 100644
index 000000000..34a70e4a4
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-number
@@ -0,0 +1,3 @@
+NUM
+0
+right
diff --git a/tests/ts/libsmartcols/files/col-parent b/tests/ts/libsmartcols/files/col-parent
new file mode 100644
index 000000000..86fe08ced
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-parent
@@ -0,0 +1,3 @@
+PARENT
+0
+right
diff --git a/tests/ts/libsmartcols/files/col-strict b/tests/ts/libsmartcols/files/col-strict
new file mode 100644
index 000000000..62bb96b9a
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-strict
@@ -0,0 +1,3 @@
+STRICT
+20
+strictwidth,right
diff --git a/tests/ts/libsmartcols/files/col-string b/tests/ts/libsmartcols/files/col-string
new file mode 100644
index 000000000..7e2904b9f
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-string
@@ -0,0 +1,3 @@
+STRINGS
+0
+none
diff --git a/tests/ts/libsmartcols/files/col-tree b/tests/ts/libsmartcols/files/col-tree
new file mode 100644
index 000000000..507688000
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-tree
@@ -0,0 +1,3 @@
+TREE
+0
+tree
diff --git a/tests/ts/libsmartcols/files/col-trunc b/tests/ts/libsmartcols/files/col-trunc
new file mode 100644
index 000000000..2887b4314
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-trunc
@@ -0,0 +1,3 @@
+TRUNC
+0
+trunc
diff --git a/tests/ts/libsmartcols/files/col-wrap b/tests/ts/libsmartcols/files/col-wrap
new file mode 100644
index 000000000..dc4ca340e
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-wrap
@@ -0,0 +1,3 @@
+WRAP
+0
+wrap
diff --git a/tests/ts/libsmartcols/files/col-wrapnl b/tests/ts/libsmartcols/files/col-wrapnl
new file mode 100644
index 000000000..0a18fd146
--- /dev/null
+++ b/tests/ts/libsmartcols/files/col-wrapnl
@@ -0,0 +1,3 @@
+WRAPNL
+0
+wrapnl
diff --git a/tests/ts/libsmartcols/files/data-id b/tests/ts/libsmartcols/files/data-id
new file mode 100644
index 000000000..f00c965d8
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-id
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
diff --git a/tests/ts/libsmartcols/files/data-number b/tests/ts/libsmartcols/files/data-number
new file mode 100644
index 000000000..562d75061
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-number
@@ -0,0 +1,10 @@
+0
+100
+21
+3
+411
+5111
+678993321
+7666666
+8765
+987456
diff --git a/tests/ts/libsmartcols/files/data-number-tiny b/tests/ts/libsmartcols/files/data-number-tiny
new file mode 100644
index 000000000..8b1acc12b
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-number-tiny
@@ -0,0 +1,10 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
diff --git a/tests/ts/libsmartcols/files/data-parent b/tests/ts/libsmartcols/files/data-parent
new file mode 100644
index 000000000..aa5071608
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-parent
@@ -0,0 +1,10 @@
+0
+1
+1
+1
+2
+2
+3
+7
+8
+7
diff --git a/tests/ts/libsmartcols/files/data-string b/tests/ts/libsmartcols/files/data-string
new file mode 100644
index 000000000..dff6e9c80
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-string
@@ -0,0 +1,10 @@
+aaaa
+bbb
+ccccc
+dddddd
+ee
+ffff
+gggggg
+hhh
+iiiiii
+jj
diff --git a/tests/ts/libsmartcols/files/data-string-extreme b/tests/ts/libsmartcols/files/data-string-extreme
new file mode 100644
index 000000000..6fb395d7a
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-string-extreme
@@ -0,0 +1,10 @@
+qqqqqqX
+ddddddddX
+ffffffffffffffffffffffffffffffffffX
+sssX
+ddX
+jjjjjX
+mmmmmmmX
+llllllllllX
+yyyyyyX
+pppppX
diff --git a/tests/ts/libsmartcols/files/data-string-long b/tests/ts/libsmartcols/files/data-string-long
new file mode 100644
index 000000000..1b5683aa4
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-string-long
@@ -0,0 +1,10 @@
+qqqqqqqqqqqqqqqqqX
+dddddddddddddX
+ffffffffffffffffffffffffffffffffffffffffX
+ssssssssssX
+ddddddddddddddddddddddddddX
+jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjX
+mmmmmmmmmmmmmmmmmmmX
+lllllllllllllllllllllllllllllllllllllX
+yyyyyyyyyyyyyyyyyyyyyyyyyyyyX
+pppppppppX
diff --git a/tests/ts/libsmartcols/files/data-string-nl b/tests/ts/libsmartcols/files/data-string-nl
new file mode 100644
index 000000000..7822e57bc
--- /dev/null
+++ b/tests/ts/libsmartcols/files/data-string-nl
@@ -0,0 +1,10 @@
+aaa
+bbbbb
+cccc\nCCCC
+dddddddd\nDDDD\nDD
+hello\nbaby
+aaa\nbbb\nccc\nddd
+eee
+fffff
+g\nhhhhh
+ppppppppp
diff --git a/tests/ts/libsmartcols/fromfile b/tests/ts/libsmartcols/fromfile
new file mode 100755
index 000000000..311dd7e1e
--- /dev/null
+++ b/tests/ts/libsmartcols/fromfile
@@ -0,0 +1,240 @@
+#!/bin/bash
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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 General Public License for more details.
+#
+#
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="fromfile"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+TESTPROG="$TS_HELPER_LIBSMARTCOLS_FROMFILE"
+ts_check_test_command "$TESTPROG"
+
+ts_init_subtest "tree"
+$TESTPROG --nlines 10 \
+ --tree-id-column 1 \
+ --tree-parent-column 2 \
+ --column $TS_SELF/files/col-tree \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-string \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "tree-json"
+$TESTPROG --nlines 10 --json \
+ --tree-id-column 1 \
+ --tree-parent-column 2 \
+ --column $TS_SELF/files/col-tree \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-string \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "tree-middle"
+$TESTPROG --nlines 10 \
+ --tree-id-column 0 \
+ --tree-parent-column 1 \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-tree \
+ --column $TS_SELF/files/col-string \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "tree-end"
+$TESTPROG --nlines 10 \
+ --tree-id-column 0 \
+ --tree-parent-column 1 \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-string \
+ --column $TS_SELF/files/col-tree \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string-long \
+ $TS_SELF/files/data-string \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "trunc"
+$TESTPROG --nlines 10 --width 40 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-trunc \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "right"
+$TESTPROG --nlines 10 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-string \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "right-maxout"
+$TESTPROG --nlines 10 --maxout --width 80\
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "strictwidth"
+$TESTPROG --nlines 10 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-strict \
+ --column $TS_SELF/files/col-number \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number-tiny \
+ $TS_SELF/files/data-number \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "noextremes"
+$TESTPROG --nlines 10 --width 45 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-noextremes \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-string-extreme \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "hidden"
+$TESTPROG --nlines 10 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-hidden \
+ --column $TS_SELF/files/col-number \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-string-long \
+ $TS_SELF/files/data-number \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "wrap"
+$TESTPROG --nlines 10 --width 40 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-wrap \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "wrap-tree"
+$TESTPROG --nlines 10 --width 45 \
+ --tree-id-column 1 \
+ --tree-parent-column 2 \
+ --column $TS_SELF/files/col-tree \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-wrap \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "wrapnl"
+$TESTPROG --nlines 10 \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-wrapnl \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-nl \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "wrapnl-tree"
+$TESTPROG --nlines 10 \
+ --tree-id-column 1 \
+ --tree-parent-column 2 \
+ --column $TS_SELF/files/col-tree \
+ --column $TS_SELF/files/col-id \
+ --column $TS_SELF/files/col-parent \
+ --column $TS_SELF/files/col-wrapnl \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-id \
+ $TS_SELF/files/data-parent \
+ $TS_SELF/files/data-string-nl \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "raw"
+$TESTPROG --nlines 10 --raw \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-trunc \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "export"
+$TESTPROG --nlines 10 --export \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-trunc \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_init_subtest "column-separator"
+$TESTPROG --nlines 10 --colsep \| \
+ --column $TS_SELF/files/col-name \
+ --column $TS_SELF/files/col-number \
+ --column $TS_SELF/files/col-trunc \
+ $TS_SELF/files/data-string \
+ $TS_SELF/files/data-number \
+ $TS_SELF/files/data-string-long \
+ >> $TS_OUTPUT 2>&1
+ts_finalize_subtest
+
+ts_log "...done."
+ts_finalize
diff --git a/tests/ts/libsmartcols/title b/tests/ts/libsmartcols/title
new file mode 100755
index 000000000..a9ba6a4fd
--- /dev/null
+++ b/tests/ts/libsmartcols/title
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# This file is part of util-linux.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This file 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 General Public License for more details.
+#
+#
+
+TS_TOPDIR="${0%/*}/../.."
+TS_DESC="title"
+
+. $TS_TOPDIR/functions.sh
+ts_init "$*"
+
+TESTPROG="$TS_HELPER_LIBSMARTCOLS_TITLE"
+ts_check_test_command "$TESTPROG"
+
+$TESTPROG --width 80 >> $TS_OUTPUT 2>&1
+
+ts_finalize
--
2.14.4

114
SOURCES/0155-lslogins-fix-password-verification.patch

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
From f769cb435c4db2e7f6d11e14fe87a1c81e0912fe Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 23 May 2018 12:43:26 +0200
Subject: [PATCH 155/173] lslogins: fix password verification

Let's follow the standard $id$salt$encrypted password format in
verification code.

The current code is useless and for example PWD-LOCK column is always
FALSE.

Upstream: http://github.com/karelzak/util-linux/commit/214fbec40abf0432b8e7968f05024ee76d11b3c7
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1581611
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/lslogins.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/login-utils/lslogins.c b/login-utils/lslogins.c
index d7a24b1fb..041053625 100644
--- a/login-utils/lslogins.c
+++ b/login-utils/lslogins.c
@@ -541,14 +541,84 @@ static int get_nprocs(const uid_t uid)
return nprocs;
}
+static const char *get_pwd_method(const char *str, const char **next, unsigned int *sz)
+{
+ const char *p = str;
+ const char *res = NULL;
+
+ if (!p || *p++ != '$')
+ return NULL;
+
+ if (sz)
+ *sz = 0;
+
+ switch (*p) {
+ case '1':
+ res = "MD5";
+ if (sz)
+ *sz = 22;
+ break;
+ case '2':
+ p++;
+ if (*p == 'a' || *p == 'y')
+ res = "Blowfish";
+ break;
+ case '5':
+ res = "SHA-256";
+ if (sz)
+ *sz = 43;
+ break;
+ case '6':
+ res = "SHA-512";
+ if (sz)
+ *sz = 86;
+ break;
+ default:
+ return NULL;
+ }
+ p++;
+
+ if (!*p || *p != '$')
+ return NULL;
+ if (next)
+ *next = ++p;
+ return res;
+}
+
+#define is_valid_pwd_char(x) (isalnum((unsigned char) (x)) || (x) == '.' || (x) == '/')
+
static int valid_pwd(const char *str)
{
- const char *p;
+ const char *p = str;
+ unsigned int sz = 0, n;
+
+ /* $id$ */
+ if (get_pwd_method(str, &p, &sz) == NULL)
+ return 0;
+ if (!*p)
+ return 0;
- for (p = str; p && *p; p++)
- if (!isalnum((unsigned int) *p))
+ /* salt$ */
+ for (; p && *p; p++) {
+ if (*p == '$') {
+ p++;
+ break;
+ }
+ if (!is_valid_pwd_char(*p))
return 0;
- return p > str ? 1 : 0;
+ }
+ if (!*p)
+ return 0;
+
+ /* encrypted */
+ for (n = 0; p && *p; p++, n++) {
+ if (!is_valid_pwd_char(*p))
+ return 0;
+ }
+
+ if (sz && n != sz)
+ return 0;
+ return 1;
}
static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const char *username)
--
2.14.4

53
SOURCES/0156-umount-add-note-about-lazy.patch

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
From 0ae2aa6a43a852cb0326faade1532c02aa7617a4 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Fri, 20 Apr 2018 09:50:04 +0200
Subject: [PATCH 156/173] umount: add note about --lazy

Unfortunately, it's pretty common that users on production systems use
lazy umount to fix some FS issues. The usual result is unwanted system
reboot, because -l is not the right way how to fix unreachable NFS or
mess with local FS with submounts.

Note that after lazy umount /proc/self/mountinfo does not contain the
FS entry, but kernel still references the FS. It makes it very
difficult to debug.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1566674
Suggested-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
Upstream: http://github.com/karelzak/util-linux/commit/031800ff6c66b4d62229cfd116195950a718a21c
---
sys-utils/umount.8 | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/sys-utils/umount.8 b/sys-utils/umount.8
index f0a712b06..71c2155b4 100644
--- a/sys-utils/umount.8
+++ b/sys-utils/umount.8
@@ -54,7 +54,8 @@ working directory there, or when a swap file on it is in use. The
offending process could even be
.B umount
itself - it opens libc, and libc in its turn may open for example locale
-files. A lazy unmount avoids this problem.
+files. A lazy unmount avoids this problem, but it may introduce another
+issues. See \fB\-\-lazy\fR description bellow.
.SH OPTIONS
.TP
\fB\-a\fR, \fB\-\-all\fR
@@ -107,6 +108,13 @@ Unmount without writing in
Lazy unmount. Detach the filesystem from the filesystem hierarchy now,
and cleanup all references to the filesystem as soon as it is not busy
anymore. (Requires kernel 2.4.11 or later.)
+
+A system reboot would be expected in near future if you're going to use this
+option for network filesystem or local filesystem with submounts. The
+recommended use-case for \fBumount -l\fR is to prevent hangs on shutdown due to
+an unreachable network share where a normal umount will hang due to a downed
+server or a network partition. Remounts of the share will not be possible.
+
.TP
\fB\-O\fR, \fB\-\-test\-opts\fR \fIoptions,list\fR
Indicate that the actions should only be taken on file systems with the
--
2.14.4

31
SOURCES/0157-losetup-add-info-about-lazy-detach-to-manpage.patch

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
From 0258872e2b45b589481e6796aa983f8749be9ada Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 10 Aug 2017 12:37:34 +0200
Subject: [PATCH 157/173] losetup: add info about lazy detach to manpage

Upstream: http://github.com/karelzak/util-linux/commit/60eedb0a53f14aa1169713a72325421db8e1c647
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1566390
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/losetup.8 | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sys-utils/losetup.8 b/sys-utils/losetup.8
index 9a8c1d597..45c220187 100644
--- a/sys-utils/losetup.8
+++ b/sys-utils/losetup.8
@@ -80,7 +80,10 @@ without --list) is deprecated.
.IP "\fB\-c, \-\-set-capacity\fP \fIloopdev\fP
force loop driver to reread size of the file associated with the specified loop device
.IP "\fB\-d, \-\-detach\fP \fIloopdev\fP..."
-detach the file or device associated with the specified loop device(s)
+detach the file or device associated with the specified loop device(s). Note
+that since Linux v3.7 kernel uses "lazy device destruction". The detach
+operation does not return EBUSY error anymore if device is actively used by
+system, but it is marked by autoclear flag and destroyed later.
.IP "\fB\-D, \-\-detach-all\fP"
detach all associated loop devices
.IP "\fB\-f, \-\-find\fP"
--
2.14.4

44
SOURCES/0158-setarch-Fix-ppc64le-architectures.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
From e10a3a201b2b4dc6ff9957600c9bf67a2f9de38e Mon Sep 17 00:00:00 2001
From: Anton Blanchard <anton@samba.org>
Date: Mon, 7 Apr 2014 09:18:13 +1000
Subject: [PATCH 158/173] setarch: Fix ppc64le architectures

setarch currently fails on ppc64le because it tries to
use big endian architecture names. Fix it.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1562125
Upstream: http://github.com/karelzak/util-linux/commit/95bf26fd68ec7f0b2dde1f022dc79d04d1a6e620
Upstream: http://github.com/karelzak/util-linux/commit/e60b6df54e27cdb68a75ea8a056a70f60df8f025
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/setarch.c | 8 ++++++++
1 file changed, 8 insertions(+)

diff --git a/sys-utils/setarch.c b/sys-utils/setarch.c
index 051cbefcd..b03406dd3 100644
--- a/sys-utils/setarch.c
+++ b/sys-utils/setarch.c
@@ -149,11 +149,19 @@ set_arch(const char *pers, unsigned long options, int list)
{PER_LINUX32, "linux32", NULL},
{PER_LINUX, "linux64", NULL},
#if defined(__powerpc__) || defined(__powerpc64__)
+#ifdef __BIG_ENDIAN__
{PER_LINUX32, "ppc32", "ppc"},
{PER_LINUX32, "ppc", "ppc"},
{PER_LINUX, "ppc64", "ppc64"},
{PER_LINUX, "ppc64pseries", "ppc64"},
{PER_LINUX, "ppc64iseries", "ppc64"},
+#else
+ {PER_LINUX32, "ppc32", "ppcle"},
+ {PER_LINUX32, "ppc", "ppcle"},
+ {PER_LINUX32, "ppc32le", "ppcle"},
+ {PER_LINUX32, "ppcle", "ppcle"},
+ {PER_LINUX, "ppc64le", "ppc64le"},
+#endif
#endif
#if defined(__x86_64__) || defined(__i386__) || defined(__ia64__)
{PER_LINUX32, "i386", "i386"},
--
2.14.4

717
SOURCES/0159-fallocate-backport-v2.32-164-g641af90dc.patch

@ -0,0 +1,717 @@ @@ -0,0 +1,717 @@
From 9f2a32a8fd08bb1b48f29c88bfa398fa4eb5f2a4 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 6 Jun 2018 11:59:16 +0200
Subject: [PATCH 159/173] fallocate: backport v2.32-164-g641af90dc

* add --dig-holes
* add --collapse-range
* add --insert-range
* add --zero-range

For backward compatibility with previous RHEL7 versions we keep
O_CREAT for open(). The current upstream uses O_CREAT only when
necessary.

Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1528567
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/fallocate.1 | 195 ++++++++++++++++++++++------
sys-utils/fallocate.c | 349 +++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 428 insertions(+), 116 deletions(-)

diff --git a/sys-utils/fallocate.1 b/sys-utils/fallocate.1
index 376353013..d4821dcd1 100644
--- a/sys-utils/fallocate.1
+++ b/sys-utils/fallocate.1
@@ -1,72 +1,185 @@
-.\" -*- nroff -*-
-.TH FALLOCATE 1 "September 2011" "util-linux" "User Commands"
+.TH FALLOCATE 1 "April 2014" "util-linux" "User Commands"
.SH NAME
-fallocate \- preallocate space to a file
+fallocate \- preallocate or deallocate space to a file
.SH SYNOPSIS
.B fallocate
-.RB [ \-n ]
-.RB [ \-p ]
+.RB [ \-c | \-p | \-z ]
.RB [ \-o
.IR offset ]
.B \-l
-.IR length
+.I length
+.RB [ \-n ]
+.I filename
+.PP
+.B fallocate \-d
+.RB [ \-o
+.IR offset ]
+.RB [ \-l
+.IR length ]
.I filename
.PP
.B fallocate \-x
.RB [ \-o
.IR offset ]
-.RB \-l
-.IR length
+.B \-l
+.I length
.I filename
.SH DESCRIPTION
.B fallocate
-is used to preallocate blocks to a file. For filesystems which support the
-fallocate system call, this is done quickly by allocating blocks and marking
-them as uninitialized, requiring no IO to the data blocks. This is much faster
-than creating a file by filling it with zeros.
-.PP
-As of the Linux Kernel v2.6.31, the fallocate system call is supported by the
-btrfs, ext4, ocfs2, and xfs filesystems.
+is used to manipulate the allocated disk space for a file,
+either to deallocate or preallocate it.
+For filesystems which support the fallocate system call,
+preallocation is done quickly by allocating blocks and marking them as
+uninitialized, requiring no IO to the data blocks.
+This is much faster than creating a file by filling it with zeroes.
.PP
The exit code returned by
.B fallocate
is 0 on success and 1 on failure.
-.PP
.SH OPTIONS
-The \fIlength\fR and \fIoffset\fR arguments may be followed by the multiplicative
-suffixes KiB=1024, MiB=1024*1024, and so on for GiB, TiB, PiB, EiB, ZiB and YiB
-(the "iB" is optional, e.g. "K" has the same meaning as "KiB") or the suffixes
-KB=1000, MB=1000*1000, and so on for GB, TB, PB, EB, ZB and YB.
-.IP "\fB\-n, \-\-keep-size\fP"
+The
+.I length
+and
+.I offset
+arguments may be followed by the multiplicative suffixes KiB (=1024),
+MiB (=1024*1024), and so on for GiB, TiB, PiB, EiB, ZiB, and YiB (the "iB" is
+optional, e.g., "K" has the same meaning as "KiB") or the suffixes
+KB (=1000), MB (=1000*1000), and so on for GB, TB, PB, EB, ZB, and YB.
+.PP
+The options
+.BR \-\-collapse\-range ", " \-\-dig\-holes ", " \-\-punch\-hole ,
+and
+.B \-\-zero\-range
+are mutually exclusive.
+.TP
+.BR \-c ", " \-\-collapse\-range
+Removes a byte range from a file, without leaving a hole.
+The byte range to be collapsed starts at
+.I offset
+and continues for
+.I length
+bytes.
+At the completion of the operation,
+the contents of the file starting at the location
+.IR offset + length
+will be appended at the location
+.IR offset ,
+and the file will be
+.I length
+bytes smaller.
+The option
+.B \-\-keep\-size
+may not be specified for the collapse-range operation.
+.sp
+Available since Linux 3.15 for ext4 (only for extent-based files) and XFS.
+.TP
+.BR \-d ", " \-\-dig\-holes
+Detect and dig holes.
+This makes the file sparse in-place, without using extra disk space.
+The minimum size of the hole depends on filesystem I/O block size
+(usually 4096 bytes).
+Also, when using this option,
+.B \-\-keep\-size
+is implied. If no range is specified by
+.B \-\-offset
+and
+.BR \-\-length ,
+then the entire file is analyzed for holes.
+.sp
+You can think of this option as doing a
+.RB """" "cp \-\-sparse" """"
+and then renaming the destination file to the original,
+without the need for extra disk space.
+.sp
+See \fB\-\-punch\-hole\fP for a list of supported filesystems.
+.TP
+.BR \-i ", " \-\-insert\-range
+Insert a hole of
+.I length
+bytes from
+.IR offset ,
+shifting existing data.
+.TP
+.BR \-l ", " "\-\-length " \fIlength
+Specifies the length of the range, in bytes.
+.TP
+.BR \-n ", " \-\-keep\-size
Do not modify the apparent length of the file. This may effectively allocate
blocks past EOF, which can be removed with a truncate.
-.IP "\fB\-p, \-\-punch-hole\fP"
-Punch holes in the file, the range should not exceed the length of the file.
-.IP "\fB\-o, \-\-offset\fP \fIoffset\fP
-Specifies the beginning offset of the allocation, in bytes.
-.IP "\fB\-l, \-\-length\fP \fIlength\fP
-Specifies the length of the allocation, in bytes.
-.IP "\fB\-x , \-\-posix\fP
-Enable POSIX operation mode. In that mode allocation operation always completes,
-but it may take longer time when fast allocation is not supported by the underlying filesystem.
-.IP "\fB\-h, \-\-help\fP"
-Print help and exit.
-.IP "\fB-V, \-\-version"
-Print version and exit.
+.TP
+.BR \-o ", " "\-\-offset " \fIoffset
+Specifies the beginning offset of the range, in bytes.
+.TP
+.BR \-p ", " \-\-punch\-hole
+Deallocates space (i.e., creates a hole) in the byte range starting at
+.I offset
+and continuing for
+.I length
+bytes.
+Within the specified range, partial filesystem blocks are zeroed,
+and whole filesystem blocks are removed from the file.
+After a successful call,
+subsequent reads from this range will return zeroes.
+This option may not be specified at the same time as the
+.B \-\-zero\-range
+option.
+Also, when using this option,
+.B \-\-keep\-size
+is implied.
+.sp
+Supported for XFS (since Linux 2.6.38), ext4 (since Linux 3.0),
+Btrfs (since Linux 3.7) and tmpfs (since Linux 3.5).
+.TP
+.BR \-v ", " \-\-verbose
+Enable verbose mode.
+.TP
+.BR \-x ", " \-\-posix
+Enable POSIX operation mode.
+In that mode allocation operation always completes,
+but it may take longer time when fast allocation is not supported by
+the underlying filesystem.
+.TP
+.BR \-z ", " \-\-zero\-range
+Zeroes space in the byte range starting at
+.I offset
+and continuing for
+.I length
+bytes.
+Within the specified range, blocks are preallocated for the regions
+that span the holes in the file.
+After a successful call,
+subsequent reads from this range will return zeroes.
+.sp
+Zeroing is done within the filesystem preferably by converting the
+range into unwritten extents. This approach means that the specified
+range will not be physically zeroed out on the device (except for
+partial blocks at the either end of the range), and I/O is
+(otherwise) required only to update metadata.
+.sp
+Option \fB\-\-keep\-size\fP can be specified to prevent file length
+modification.
+.sp
+Available since Linux 3.14 for ext4 (only for extent-based files) and XFS.
+.TP
+.BR \-V ", " \-\-version
+Display version information and exit.
+.TP
+.BR \-h ", " \-\-help
+Display help text and exit.
.SH AUTHORS
-.UR sandeen@redhat.com
+.MT sandeen@redhat.com
Eric Sandeen
-.UE
+.ME
.br
-.UR kzak@redhat.com
+.MT kzak@redhat.com
Karel Zak
-.UE
+.ME
.SH SEE ALSO
+.BR truncate (1),
.BR fallocate (2),
-.BR posix_fallocate (3),
-.BR truncate (1)
+.BR posix_fallocate (3)
.SH AVAILABILITY
The fallocate command is part of the util-linux package and is available from
-.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
+.UR https://\:www.kernel.org\:/pub\:/linux\:/utils\:/util-linux/
Linux Kernel Archive
.UE .
diff --git a/sys-utils/fallocate.c b/sys-utils/fallocate.c
index 17ae5fe69..75d89a7a9 100644
--- a/sys-utils/fallocate.c
+++ b/sys-utils/fallocate.c
@@ -23,6 +23,7 @@
*/
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
@@ -31,50 +32,110 @@
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
+#include <string.h>
#ifndef HAVE_FALLOCATE
# include <sys/syscall.h>
#endif
-#ifdef HAVE_LINUX_FALLOC_H
-# include <linux/falloc.h> /* for FALLOC_FL_* flags */
+#if defined(HAVE_LINUX_FALLOC_H) && \
+ (!defined(FALLOC_FL_KEEP_SIZE) || !defined(FALLOC_FL_PUNCH_HOLE) || \
+ !defined(FALLOC_FL_COLLAPSE_RANGE) || !defined(FALLOC_FL_ZERO_RANGE) || \
+ !defined(FALLOC_FL_INSERT_RANGE))
+# include <linux/falloc.h> /* non-libc fallback for FALLOC_FL_* flags */
#endif
+
#ifndef FALLOC_FL_KEEP_SIZE
-# define FALLOC_FL_KEEP_SIZE 1
+# define FALLOC_FL_KEEP_SIZE 0x1
#endif
#ifndef FALLOC_FL_PUNCH_HOLE
-# define FALLOC_FL_PUNCH_HOLE 2
+# define FALLOC_FL_PUNCH_HOLE 0x2
+#endif
+
+#ifndef FALLOC_FL_COLLAPSE_RANGE
+# define FALLOC_FL_COLLAPSE_RANGE 0x8
+#endif
+
+#ifndef FALLOC_FL_ZERO_RANGE
+# define FALLOC_FL_ZERO_RANGE 0x10
+#endif
+
+#ifndef FALLOC_FL_INSERT_RANGE
+# define FALLOC_FL_INSERT_RANGE 0x20
#endif
#include "nls.h"
#include "strutils.h"
#include "c.h"
#include "closestream.h"
+#include "xalloc.h"
#include "optutils.h"
-static void __attribute__((__noreturn__)) usage(FILE *out)
+static int verbose;
+static char *filename;
+
+static void __attribute__((__noreturn__)) usage(void)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out,
_(" %s [options] <filename>\n"), program_invocation_short_name);
+
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Preallocate space to, or deallocate space from a file.\n"), out);
+
fputs(USAGE_OPTIONS, out);
- fputs(_(" -n, --keep-size don't modify the length of the file\n"
- " -p, --punch-hole punch holes in the file\n"
- " -o, --offset <num> offset of the allocation, in bytes\n"
- " -l, --length <num> length of the allocation, in bytes\n"), out);
+ fputs(_(" -c, --collapse-range remove a range from the file\n"), out);
+ fputs(_(" -d, --dig-holes detect zeroes and replace with holes\n"), out);
+ fputs(_(" -i, --insert-range insert a hole at range, shifting existing data\n"), out);
+ fputs(_(" -l, --length <num> length for range operations, in bytes\n"), out);
+ fputs(_(" -n, --keep-size maintain the apparent size of the file\n"), out);
+ fputs(_(" -o, --offset <num> offset for range operations, in bytes\n"), out);
+ fputs(_(" -p, --punch-hole replace a range with a hole (implies -n)\n"), out);
+ fputs(_(" -z, --zero-range zero and ensure allocation of a range\n"), out);
#ifdef HAVE_POSIX_FALLOCATE
- fputs(_(" -x, --posix use posix_fallocate(3) instead of fallocate(2)\n"), out);
+ fputs(_(" -x, --posix use posix_fallocate(3) instead of fallocate(2)\n"), out);
#endif
+ fputs(_(" -v, --verbose verbose mode\n"), out);
+
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("fallocate(1)"));
+ printf(USAGE_HELP_OPTIONS(22));
+
+ printf(USAGE_MAN_TAIL("fallocate(1)"));
- exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
}
+static loff_t cvtnum(char *s)
+{
+ uintmax_t x;
+
+ if (strtosize(s, &x))
+ return -1LL;
+
+ return x;
+}
+
+static void xfallocate(int fd, int mode, off_t offset, off_t length)
+{
+ int error;
+#ifdef HAVE_FALLOCATE
+ error = fallocate(fd, mode, offset, length);
+#else
+ error = syscall(SYS_fallocate, fd, mode, offset, length);
+#endif
+ /*
+ * EOPNOTSUPP: The FALLOC_FL_KEEP_SIZE is unsupported
+ * ENOSYS: The filesystem does not support sys_fallocate
+ */
+ if (error < 0) {
+ if ((mode & FALLOC_FL_KEEP_SIZE) && errno == EOPNOTSUPP)
+ errx(EXIT_FAILURE, _("fallocate failed: keep size mode is unsupported"));
+ err(EXIT_FAILURE, _("fallocate failed"));
+ }
+}
#ifdef HAVE_POSIX_FALLOCATE
static void xposix_fallocate(int fd, off_t offset, off_t length)
@@ -86,41 +147,163 @@ static void xposix_fallocate(int fd, off_t offset, off_t length)
}
#endif
+/* The real buffer size has to be bufsize + sizeof(uintptr_t) */
+static int is_nul(void *buf, size_t bufsize)
+{
+ typedef uintptr_t word;
+ void const *vp;
+ char const *cbuf = buf, *cp;
+ word const *wp = buf;
-static loff_t cvtnum(char *s)
+ /* set sentinel */
+ memset((char *) buf + bufsize, '\1', sizeof(word));
+
+ /* Find first nonzero *word*, or the word with the sentinel. */
+ while (*wp++ == 0)
+ continue;
+
+ /* Find the first nonzero *byte*, or the sentinel. */
+ vp = wp - 1;
+ cp = vp;
+
+ while (*cp++ == 0)
+ continue;
+
+ return cbuf + bufsize < cp;
+}
+
+static void dig_holes(int fd, off_t file_off, off_t len)
{
- uintmax_t x;
+ off_t file_end = len ? file_off + len : 0;
+ off_t hole_start = 0, hole_sz = 0;
+ uintmax_t ct = 0;
+ size_t bufsz;
+ char *buf;
+ struct stat st;
+#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
+ off_t cache_start = file_off;
+ /*
+ * We don't want to call POSIX_FADV_DONTNEED to discard cached
+ * data in PAGE_SIZE steps. IMHO it's overkill (too many syscalls).
+ *
+ * Let's assume that 1MiB (on system with 4K page size) is just
+ * a good compromise.
+ * -- kzak Feb-2014
+ */
+ const size_t cachesz = getpagesize() * 256;
+#endif
- if (strtosize(s, &x))
- return -1LL;
+ if (fstat(fd, &st) != 0)
+ err(EXIT_FAILURE, _("stat of %s failed"), filename);
- return x;
+ bufsz = st.st_blksize;
+
+ if (lseek(fd, file_off, SEEK_SET) < 0)
+ err(EXIT_FAILURE, _("seek on %s failed"), filename);
+
+ /* buffer + extra space for is_nul() sentinel */
+ buf = xmalloc(bufsz + sizeof(uintptr_t));
+ while (file_end == 0 || file_off < file_end) {
+ /*
+ * Detect data area (skip holes)
+ */
+ off_t end, off;
+
+ off = lseek(fd, file_off, SEEK_DATA);
+ if ((off == -1 && errno == ENXIO) ||
+ (file_end && off >= file_end))
+ break;
+
+ end = lseek(fd, off, SEEK_HOLE);
+ if (file_end && end > file_end)
+ end = file_end;
+
+#if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
+ posix_fadvise(fd, off, end, POSIX_FADV_SEQUENTIAL);
+#endif
+ /*
+ * Dig holes in the area
+ */
+ while (off < end) {
+ ssize_t rsz = pread(fd, buf, bufsz, off);
+ if (rsz < 0 && errno)
+ err(EXIT_FAILURE, _("%s: read failed"), filename);
+ if (end && rsz > 0 && off > end - rsz)
+ rsz = end - off;
+ if (rsz <= 0)
+ break;
+
+ if (is_nul(buf, rsz)) {
+ if (!hole_sz) /* new hole detected */
+ hole_start = off;
+ hole_sz += rsz;
+ } else if (hole_sz) {
+ xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+ hole_start, hole_sz);
+ ct += hole_sz;
+ hole_sz = hole_start = 0;
+ }
+
+#if defined(POSIX_FADV_DONTNEED) && defined(HAVE_POSIX_FADVISE)
+ /* discard cached data */
+ if (off - cache_start > (off_t) cachesz) {
+ size_t clen = off - cache_start;
+
+ clen = (clen / cachesz) * cachesz;
+ posix_fadvise(fd, cache_start, clen, POSIX_FADV_DONTNEED);
+ cache_start = cache_start + clen;
+ }
+#endif
+ off += rsz;
+ }
+ if (hole_sz) {
+ xfallocate(fd, FALLOC_FL_PUNCH_HOLE|FALLOC_FL_KEEP_SIZE,
+ hole_start, hole_sz);
+ ct += hole_sz;
+ }
+ file_off = off;
+ }
+
+ free(buf);
+
+ if (verbose) {
+ char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, ct);
+ fprintf(stdout, _("%s: %s (%ju bytes) converted to sparse holes.\n"),
+ filename, str, ct);
+ free(str);
+ }
}
int main(int argc, char **argv)
{
- char *fname;
int c;
- int error = 0;
int fd;
int mode = 0;
- int posix = 0;
+ int dig = 0;
+ int posix = 0;
loff_t length = -2LL;
loff_t offset = 0;
static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "version", 0, 0, 'V' },
- { "keep-size", 0, 0, 'n' },
- { "punch-hole", 0, 0, 'p' },
- { "offset", 1, 0, 'o' },
- { "length", 1, 0, 'l' },
- { "posix", 0, 0, 'x' },
- { NULL, 0, 0, 0 }
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "keep-size", no_argument, NULL, 'n' },
+ { "punch-hole", no_argument, NULL, 'p' },
+ { "collapse-range", no_argument, NULL, 'c' },
+ { "dig-holes", no_argument, NULL, 'd' },
+ { "insert-range", no_argument, NULL, 'i' },
+ { "zero-range", no_argument, NULL, 'z' },
+ { "offset", required_argument, NULL, 'o' },
+ { "length", required_argument, NULL, 'l' },
+ { "posix", no_argument, NULL, 'x' },
+ { "verbose", no_argument, NULL, 'v' },
+ { NULL, 0, NULL, 0 }
};
- static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
- { 'x', 'n', 'p' },
+ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
+ { 'c', 'd', 'p', 'z' },
+ { 'c', 'n' },
+ { 'x', 'c', 'd', 'i', 'n', 'p', 'z'},
{ 0 }
};
int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
@@ -130,29 +313,39 @@ int main(int argc, char **argv)
textdomain(PACKAGE);
atexit(close_stdout);
- while ((c = getopt_long(argc, argv, "hVnpl:o:x", longopts, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "hvVncpdizxl:o:", longopts, NULL))
+ != -1) {
err_exclusive_options(c, longopts, excl, excl_st);
switch(c) {
case 'h':
- usage(stdout);
+ usage();
break;
- case 'V':
- printf(UTIL_LINUX_VERSION);
- return EXIT_SUCCESS;
- case 'p':
- mode |= FALLOC_FL_PUNCH_HOLE;
- /* fall through */
- case 'n':
- mode |= FALLOC_FL_KEEP_SIZE;
+ case 'c':
+ mode |= FALLOC_FL_COLLAPSE_RANGE;
+ break;
+ case 'd':
+ dig = 1;
+ break;
+ case 'i':
+ mode |= FALLOC_FL_INSERT_RANGE;
break;
case 'l':
length = cvtnum(optarg);
break;
+ case 'n':
+ mode |= FALLOC_FL_KEEP_SIZE;
+ break;
case 'o':
offset = cvtnum(optarg);
break;
+ case 'p':
+ mode |= FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+ break;
+ case 'z':
+ mode |= FALLOC_FL_ZERO_RANGE;
+ break;
case 'x':
#ifdef HAVE_POSIX_FALLOCATE
posix = 1;
@@ -160,53 +353,59 @@ int main(int argc, char **argv)
#else
errx(EXIT_FAILURE, _("posix_fallocate support is not compiled"))
#endif
- default:
- usage(stderr);
+ case 'v':
+ verbose++;
break;
+ case 'V':
+ printf(UTIL_LINUX_VERSION);
+ return EXIT_SUCCESS;
+ default:
+ errtryhelp(EXIT_FAILURE);
}
}
- if (length == -2LL)
- errx(EXIT_FAILURE, _("no length argument specified"));
- if (length <= 0)
- errx(EXIT_FAILURE, _("invalid length value specified"));
- if (offset < 0)
- errx(EXIT_FAILURE, _("invalid offset value specified"));
if (optind == argc)
- errx(EXIT_FAILURE, _("no filename specified."));
+ errx(EXIT_FAILURE, _("no filename specified"));
+
+ filename = argv[optind++];
- fname = argv[optind++];
+ if (optind != argc)
+ errx(EXIT_FAILURE, _("unexpected number of arguments"));
- if (optind != argc) {
- warnx(_("unexpected number of arguments"));
- usage(stderr);
+ if (dig) {
+ /* for --dig-holes the default is analyze all file */
+ if (length == -2LL)
+ length = 0;
+ if (length < 0)
+ errx(EXIT_FAILURE, _("invalid length value specified"));
+ } else {
+ /* it's safer to require the range specification (--length --offset) */
+ if (length == -2LL)
+ errx(EXIT_FAILURE, _("no length argument specified"));
+ if (length <= 0)
+ errx(EXIT_FAILURE, _("invalid length value specified"));
}
+ if (offset < 0)
+ errx(EXIT_FAILURE, _("invalid offset value specified"));
- fd = open(fname, O_WRONLY|O_CREAT, 0644);
+ /* O_CREAT makes sense only for the default fallocate(2) behavior
+ * when mode is no specified and new space is allocated
+ *
+ * RHEL7.6: for backward compatibility in RHEL7 we keep O_CREAT there.
+ */
+ fd = open(filename, O_RDWR | O_CREAT,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd < 0)
- err(EXIT_FAILURE, _("cannot open %s"), fname);
+ err(EXIT_FAILURE, _("cannot open %s"), filename);
+ if (dig)
+ dig_holes(fd, offset, length);
#ifdef HAVE_POSIX_FALLOCATE
- if (posix)
+ else if (posix)
xposix_fallocate(fd, offset, length);
- else
#endif
-
-#ifdef HAVE_FALLOCATE
- error = fallocate(fd, mode, offset, length);
-#else
- error = syscall(SYS_fallocate, fd, mode, offset, length);
-#endif
- /*
- * EOPNOTSUPP: The FALLOC_FL_KEEP_SIZE is unsupported
- * ENOSYS: The filesystem does not support sys_fallocate
- */
- if (error < 0) {
- if ((mode & FALLOC_FL_KEEP_SIZE) && errno == EOPNOTSUPP)
- errx(EXIT_FAILURE,
- _("keep size mode (-n option) unsupported"));
- err(EXIT_FAILURE, _("%s: fallocate failed"), fname);
- }
+ else
+ xfallocate(fd, mode, offset, length);
close(fd);
return EXIT_SUCCESS;
--
2.14.4

54
SOURCES/0160-libmount-fix-mnt_table_is_fs_mounted-for-rbind.patch

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
From 7f5f61824b3b7ffa81d34481aec5a7ecca213a5a Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 3 Jan 2018 13:59:59 +0100
Subject: [PATCH 160/173] libmount: fix mnt_table_is_fs_mounted() for rbind

There is no difference between "bind" and "rbind" if we want to FS
root to search for the FS in mountinfo file.

fstab:

/dev/sdc1 /mnt/foo xfs defaults 0 0
/mnt/foo /mnt/test none rw,rbind 0 0

use -a more than once:

mount -a
mount -a

/proc/mounts (the current result):

/dev/sdc1 /mnt/foo xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdc1 /mnt/test xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdc1 /mnt/test xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdc1 /mnt/foo xfs rw,relatime,attr2,inode64,noquota 0 0

expected (fixed version) result:

/dev/sdc1 /mnt/foo xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sdc1 /mnt/test xfs rw,relatime,attr2,inode64,noquota 0 0

Upstream: http://github.com/karelzak/util-linux/commit/b5cc232362a60b2a7738ee250609202bd6195e49
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1528959
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/tab.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libmount/src/tab.c b/libmount/src/tab.c
index 5628da6e5..dfa1da822 100644
--- a/libmount/src/tab.c
+++ b/libmount/src/tab.c
@@ -1099,7 +1099,8 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs)
struct libmnt_fs *rootfs;
int flags = 0;
- if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0)
+ if (mnt_fs_get_option(fstab_fs, "bind", NULL, NULL) == 0 ||
+ mnt_fs_get_option(fstab_fs, "rbind", NULL, NULL) == 0)
flags = MS_BIND;
rootfs = mnt_table_get_fs_root(tb, fstab_fs, flags, &root);
--
2.14.4

54
SOURCES/0161-mount-add-ext4-to-some-places-in-man-page.patch

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
From 7492cf62b7334792df931469ca783878b868d0d0 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 6 Jun 2018 12:10:42 +0200
Subject: [PATCH 161/173] mount: add ext4 to some places in man page

Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1538721
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/mount.8 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sys-utils/mount.8 b/sys-utils/mount.8
index 49cb2818f..35d782f0e 100644
--- a/sys-utils/mount.8
+++ b/sys-utils/mount.8
@@ -874,7 +874,7 @@ for example tune2fs -l output for extN filesystems).
The following options apply to any filesystem that is being
mounted (but not every filesystem actually honors them - e.g., the
.B sync
-option today has effect only for ext2, ext3, fat, vfat and ufs):
+option today has effect only for ext2, ext3, ext4, fat, vfat and ufs):
.TP
.B async
@@ -909,7 +909,7 @@ The
.BR context=
option is useful when mounting filesystems that do not support
extended attributes, such as a floppy or hard disk formatted with VFAT, or
-systems that are not normally running under SELinux, such as an ext3 formatted
+systems that are not normally running under SELinux, such as an ext3 or ext4 formatted
disk from a non-SELinux workstation. You can also use
.BR context=
on filesystems you do not trust, such as a floppy. It also helps in compatibility with
@@ -2833,7 +2833,7 @@ not specified or the filesystem is known for libblkid, for example:
.sp
.B "mount /tmp/disk.img /mnt"
.sp
-.B "mount -t ext3 /tmp/disk.img /mnt"
+.B "mount -t ext4 /tmp/disk.img /mnt"
.sp
.RE
This type of mount knows about four options, namely
@@ -2948,7 +2948,7 @@ It is possible for a corrupted filesystem to cause a crash.
.PP
Some Linux filesystems don't support
.B "\-o sync and \-o dirsync"
-(the ext2, ext3, fat and vfat filesystems
+(the ext2, ext3, ext4, fat and vfat filesystems
.I do
support synchronous updates (a la BSD) when mounted with the
.B sync
--
2.14.4

72
SOURCES/0162-agetty-keep-c_iflags-unmodified-on-autologin.patch

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
From 7974045302fe53629e70501f0180f30cbaa25b1e Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 6 Jun 2018 15:57:24 +0200
Subject: [PATCH 162/173] agetty: keep c_iflags unmodified on --autologin

agetty sets c_iflags according to interaction with serial line in
get_logname(). For --autologin it does not read from the line, so we
have no clue how to set the flags.

The current behavior is to zeroize the flags. Unfortunately, it seems
like bad idea, because the line may be already properly initialized by
kernel (or systemd, etc.).

The new behavior is not touch the flags on --autologin.

Upstream: http://github.com/karelzak/util-linux/commit/2c4d86abdadab19be76abecb156da7f7dc284d81
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1252764
Signed-off-by: Karel Zak <kzak@redhat.com>
---
term-utils/agetty.8 | 4 ++++
term-utils/agetty.c | 17 +++++++++++++----
2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/term-utils/agetty.8 b/term-utils/agetty.8
index a42cdf158..fe4bfd427 100644
--- a/term-utils/agetty.8
+++ b/term-utils/agetty.8
@@ -94,6 +94,10 @@ password. The \-f \fIusername\fP option is added to the \fB/bin/login\fP
command line by default. The \-\-login-options option changes this default
behaviour and then only \\u is replaced by the \fIusername\fP and no other
option is added to the login command line.
+
+Note that \fB\-\-autologin\fP may affect the way how agetty initializes the
+serial line, because on auto-login agetty does not read from the line and it
+has no opportunity optimize the line setting.
.TP
\-c, \-\-noreset
Don't reset terminal cflags (control modes). See \fItermios(3)\fP for more
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index b626cdbeb..948d77246 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -1100,13 +1100,22 @@ static void termio_init(struct options *op, struct termios *tp)
/* Flush input and output queues, important for modems! */
tcflush(STDIN_FILENO, TCIOFLUSH);
+ /* The defaul is set c_iflag in termio_final() according to chardata.
+ * Unfortunately, the chardata are not set according to the serial line
+ * if --autolog is enabled. In this case we do not read from the line
+ * at all. The best what we can do in this case is to keep c_iflag
+ * unmodified for --autolog.
+ */
+ if (!op->autolog) {
#ifdef IUTF8
- tp->c_iflag = tp->c_iflag & IUTF8;
- if (tp->c_iflag & IUTF8)
- op->flags |= F_UTF8;
+ tp->c_iflag = tp->c_iflag & IUTF8;
+ if (tp->c_iflag & IUTF8)
+ op->flags |= F_UTF8;
#else
- tp->c_iflag = 0;
+ tp->c_iflag = 0;
#endif
+ }
+
tp->c_lflag = 0;
tp->c_oflag &= OPOST | ONLCR;
--
2.14.4

73
SOURCES/0163-sulogin-don-t-use-strcpy-enlarge-pwd-line-buffer.patch

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
From 94f380e223e7496804dcd68e204fba0a15df8bd7 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 25 May 2015 15:24:13 +0200
Subject: [PATCH 163/173] sulogin: don't use strcpy(), enlarge pwd line buffer

* according to "man getpwnam" 16384 bytes is enough to store one
passwd entry (let's use 2*BUFSIZE to avoid magic numbers in code)

* don't use strcpy() to set empty password

Upstream: http://github.com/karelzak/util-linux/commit/d681e0956cdca1a016346424939fe1b9c6a0a549
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/sulogin.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index bbd67b3ee..6d03bc5ae 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -373,8 +373,8 @@ static struct passwd *getrootpwent(int try_manually)
struct passwd *pw;
struct spwd *spw;
FILE *fp;
- static char line[256];
- static char sline[256];
+ static char line[2 * BUFSIZ];
+ static char sline[2 * BUFSIZ];
char *p;
/*
@@ -410,7 +410,7 @@ static struct passwd *getrootpwent(int try_manually)
/*
* Find root in the password file.
*/
- while ((p = fgets(line, 256, fp)) != NULL) {
+ while ((p = fgets(line, sizeof(line), fp)) != NULL) {
if (strncmp(line, "root:", 5) != 0)
continue;
p += 5;
@@ -439,12 +439,12 @@ static struct passwd *getrootpwent(int try_manually)
/*
* The password is invalid. If there is a shadow password, try it.
*/
- strcpy(pwd.pw_passwd, "");
+ *pwd.pw_passwd = '\0';
if ((fp = fopen(_PATH_SHADOW_PASSWD, "r")) == NULL) {
warn(_("cannot open %s"), _PATH_PASSWD);
return &pwd;
}
- while ((p = fgets(sline, 256, fp)) != NULL) {
+ while ((p = fgets(sline, sizeof(sline), fp)) != NULL) {
if (strncmp(sline, "root:", 5) != 0)
continue;
p += 5;
@@ -458,11 +458,11 @@ static struct passwd *getrootpwent(int try_manually)
*/
if (p == NULL) {
warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
- strcpy(pwd.pw_passwd, "");
+ *pwd.pw_passwd = '\0';
}
if (!valid(pwd.pw_passwd)) {
warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
- strcpy(pwd.pw_passwd, "");
+ *pwd.pw_passwd = '\0';
}
return &pwd;
}
--
2.14.4

175
SOURCES/0164-sulogin-improve-support-for-locked-root-account.patch

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
From a08c1a6aadaa27e4070fe58242d55464d6c7a3e7 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 25 May 2015 15:30:52 +0200
Subject: [PATCH 164/173] sulogin: improve support for locked root account

Some installations and distributions don't use a root account password
for security reasons and use sudo instead. In that case, asking for the
password makes no sense, and it is not even considered as valid as it's just
"*" or "!".

In these cases --force is required to just start a root shell and no
ask for password.

I don't think it's a good idea to automatically start root shell when
locked account is detected. It's possible that the machine is on
public place and for example Ubuntu uses root account disabled by
default (and also Fedora when installed by yum/dnf without anaconda).

The --force option forces admins to think about it...

The distro maintainers can also use --force in their initscripts or
systemd emergency.service if they believe that promiscuous setting is
the right thing for the distro.

Addresses: https://bugs.debian.org/326678
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
Upstream: http://github.com/karelzak/util-linux/commit/7ff1162e67164cb4ece19dd809c26272461aa254
Signed-off-by: Karel Zak <kzak@redhat.com>
---
login-utils/sulogin.8 | 13 +++++++++----
login-utils/sulogin.c | 48 ++++++++++++++++++++++++++++++++++--------------
2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/login-utils/sulogin.8 b/login-utils/sulogin.8
index b9dec165c..702487985 100644
--- a/login-utils/sulogin.8
+++ b/login-utils/sulogin.8
@@ -35,8 +35,10 @@ Give root password for system maintenance
.br
(or type Control\-D for normal startup):
.PP
-.I sulogin
-will be connected to the current terminal, or to the optional tty device that
+If the root account is locked and --force is specified, no password is required.
+.PP
+.B sulogin
+will be connected to the current terminal, or to the optional \fItty\fR device that
can be specified on the command line (typically
.BR /dev/console ).
.PP
@@ -50,8 +52,11 @@ from the system fails, manually examine
.I /etc/passwd
and
.I /etc/shadow
-to get the password. If they are damaged or nonexistent, sulogin will start
-a root shell without asking for a password.
+to get the password. If these files are damaged or nonexistent, or when
+root account is locked by '!' or '*' at the begin of the password then
+.B sulogin
+will \fBstart a root shell without asking for a password\fP.
+.PP
.IP
Only use the
.B \-e
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index 6d03bc5ae..a17b91d71 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -81,6 +81,13 @@ static volatile sig_atomic_t sigchild;
# define IUCLC 0
#endif
+static int locked_account_password(const char *passwd)
+{
+ if (passwd && (*passwd == '*' || *passwd == '!'))
+ return 1;
+ return 0;
+}
+
/*
* Fix the tty modes and set reasonable defaults.
*/
@@ -423,7 +430,6 @@ static struct passwd *getrootpwent(int try_manually)
p = line;
break;
}
-
fclose(fp);
/*
@@ -460,7 +466,8 @@ static struct passwd *getrootpwent(int try_manually)
warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
*pwd.pw_passwd = '\0';
}
- if (!valid(pwd.pw_passwd)) {
+ /* locked accont passwords are valid too */
+ if (!locked_account_password(pwd.pw_passwd) && !valid(pwd.pw_passwd)) {
warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
*pwd.pw_passwd = '\0';
}
@@ -470,7 +477,7 @@ static struct passwd *getrootpwent(int try_manually)
/*
* Ask by prompt for the password.
*/
-static void doprompt(const char *crypted, struct console *con)
+static void doprompt(const char *crypted, struct console *con, int deny)
{
struct termios tty;
@@ -487,18 +494,25 @@ static void doprompt(const char *crypted, struct console *con)
if ((con->file = fdopen(con->fd, "r+")) == (FILE*)0)
goto err;
}
+
+ if (deny)
+ fprintf(con->file, _("\nCannot open access to console, the root account is locked.\n"
+ "See sulogin(8) man page for more details.\n\n"
+ "Press Enter to continue.\n"));
+ else {
#if defined(USE_ONELINE)
- if (crypted[0])
- fprintf(con->file, _("Give root password for login: "));
- else
- fprintf(con->file, _("Press enter for login: "));
+ if (crypted[0] && !locked_account_password(crypted))
+ fprintf(con->file, _("Give root password for login: "));
+ else
+ fprintf(con->file, _("Press Enter for login: "));
#else
- if (crypted[0])
- fprintf(con->file, _("Give root password for maintenance\n"));
- else
- fprintf(con->file, _("Press enter for maintenance"));
- fprintf(con->file, _("(or type Control-D to continue): "));
+ if (crypted[0] && !locked_account_password(crypted))
+ fprintf(con->file, _("Give root password for maintenance\n"));
+ else
+ fprintf(con->file, _("Press Enter for maintenance\n"));
+ fprintf(con->file, _("(or press Control-D to continue): "));
#endif
+ }
fflush(con->file);
err:
if (con->flags & CON_SERIAL)
@@ -914,6 +928,7 @@ int main(int argc, char **argv)
goto nofork;
}
+
mask_signal(SIGCHLD, chld_handler, &saved_sigchld);
do {
con = list_entry(ptr, struct console, entry);
@@ -930,12 +945,17 @@ int main(int argc, char **argv)
const char *passwd = pwd->pw_passwd;
const char *answer;
int failed = 0, doshell = 0;
+ int deny = !opt_e && locked_account_password(pwd->pw_passwd);
+
+ doprompt(passwd, con, deny);
- doprompt(passwd, con);
if ((answer = getpasswd(con)) == NULL)
break;
+ if (deny)
+ exit(EXIT_FAILURE);
- if (passwd[0] == '\0')
+ /* no password or locked account */
+ if (!passwd[0] || locked_account_password(passwd))
doshell++;
else {
const char *cryptbuf;
--
2.14.4

34
SOURCES/0165-sulogin-Always-make-echo-work-after-performing-getpa.patch

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
From 6bb8e6d4c38f260109852ef8b43876ea1aff3810 Mon Sep 17 00:00:00 2001
From: Werner Fink <werner@suse.de>
Date: Tue, 22 Mar 2016 10:38:59 +0100
Subject: [PATCH 165/173] sulogin: Always make echo work after performing
getpasswd even if root account is locked

If the root account is locked and no password was provided then the terminal
line is not set back to do echo of the input. This correct a small overlook
in commit 7ff1162e67164cb4ece19dd809c26272461aa254

Upstream: http://github.com/karelzak/util-linux/commit/6988998b66b4b95c494d60599f8e3de2ffbaeece
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
Signed-off-by: Werner Fink <werner@suse.de>
---
login-utils/sulogin.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index a17b91d71..a6918282e 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -676,8 +676,7 @@ quit:
alarm(0);
if (tc)
tcsetattr(fd, TCSAFLUSH, &con->tio);
- if (ret && *ret != '\0')
- tcfinal(con);
+ tcfinal(con);
printf("\r\n");
out:
return ret;
--
2.14.4

35
SOURCES/0166-sulogin-make-getpasswd-.-return-NULL-on-D.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From c19feb058ff5883ab7255241d13732ab66bf44f0 Mon Sep 17 00:00:00 2001
From: Andreas Henriksson <andreas@fatal.se>
Date: Mon, 28 Nov 2016 17:24:49 +0100
Subject: [PATCH 166/173] sulogin: make getpasswd(...) return NULL on ^D
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This makes the caller bail out early instead of evaluating the
input as a password.

Reported-by: Bjørn Mork <bjorn@mork.no>
Addresses: http://bugs.debian.org/846112
Upstream: http://github.com/karelzak/util-linux/commit/60dea9d187caa700e42f37c7955116f71be912d5
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
login-utils/sulogin.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index a6918282e..7ec349953 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -661,6 +661,7 @@ static char *getpasswd(struct console *con)
ptr--;
break;
case CEOF:
+ ret = NULL;
goto quit;
default:
if ((size_t)(ptr - &pass[0]) >= (sizeof(pass) -1 )) {
--
2.14.4

38
SOURCES/0167-sulogin-bail-out-from-getpasswd-.-on-timeout.patch

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
From 971b2ecede4d2040e879d9cfb56332a2e210bed8 Mon Sep 17 00:00:00 2001
From: Andreas Henriksson <andreas@fatal.se>
Date: Mon, 28 Nov 2016 17:24:50 +0100
Subject: [PATCH 167/173] sulogin: bail out from getpasswd(...) on timeout
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If timeout happens while waiting in prompt, bail out instead
of retrying.

Reported-by: Bjørn Mork <bjorn@mork.no>
Addresses: http://bugs.debian.org/846107
Upstream: http://github.com/karelzak/util-linux/commit/1c4b2d43926e2a7032310cd18b411d8d872cb4ed
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1561200
Signed-off-by: Andreas Henriksson <andreas@fatal.se>
---
login-utils/sulogin.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index 7ec349953..dd73a1c50 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -611,6 +611,10 @@ static char *getpasswd(struct console *con)
while (cp->eol == '\0') {
if (read(fd, &c, 1) < 1) {
if (errno == EINTR || errno == EAGAIN) {
+ if (alarm_rised) {
+ ret = NULL;
+ goto quit;
+ }
usleep(1000);
continue;
}
--
2.14.4

40
SOURCES/0168-losetup-keep-f-and-devname-mutually-exclusive.patch

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
From 14a4f41a94cc4bd227940c4bd976e39d9f13e8c5 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 7 Jun 2018 12:05:08 +0200
Subject: [PATCH 168/173] losetup: keep -f and <devname> mutually exclusive

losetup tries to blindly use specified device as well as search for
the first free device, the result is:

# losetup /dev/loop1 -f /tmp/tfile_loop1
losetup: /dev/loop1: failed to set up loop device: Invalid argument

fixed version:

# losetup /dev/loop10 -f img
losetup: unexpected arguments

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1566432
Upstream: http://github.com/karelzak/util-linux/commit/c3f5a0f1d47dbc47f6d21da232d4eb1cfb7905db
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/losetup.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index d9b0c9b61..8df831b8f 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -545,6 +545,9 @@ int main(int argc, char **argv)
*/
act = A_CREATE;
file = argv[optind++];
+
+ if (optind < argc)
+ errx(EXIT_FAILURE, _("unexpected arguments"));
}
if (list && !act && optind == argc)
--
2.14.4

83
SOURCES/0169-lscpu-fix-mzx-min-MHz-reporting.patch

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
From 79866c4b187e9ccf37fe333e9865a8575f4a3a16 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 6 Jun 2018 10:10:20 +0200
Subject: [PATCH 169/173] lscpu: fix mzx/min MHz reporting

Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1579439
Signed-off-by: Karel Zak <kzak@redhat.com>
---
sys-utils/lscpu.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 1ee73f34a..4c15de1d4 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -1251,6 +1251,52 @@ read_configured(struct lscpu_desc *desc, int idx)
desc->configured[idx] = path_read_s32(_PATH_SYS_CPU "/cpu%d/configure", num);
}
+/* Read overall maximum frequency of cpu */
+static char *
+cpu_max_mhz(struct lscpu_desc *desc, char *buf, size_t bufsz)
+{
+ int i;
+ float cpu_freq = 0.0;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
+
+ if (desc->present) {
+ for (i = 0; i < desc->ncpuspos; i++) {
+ if (CPU_ISSET_S(real_cpu_num(desc, i), setsize, desc->present)
+ && desc->maxmhz[i]) {
+ float freq = atof(desc->maxmhz[i]);
+
+ if (freq > cpu_freq)
+ cpu_freq = freq;
+ }
+ }
+ }
+ snprintf(buf, bufsz, "%.4f", cpu_freq);
+ return buf;
+}
+
+/* Read overall minimum frequency of cpu */
+static char *
+cpu_min_mhz(struct lscpu_desc *desc, char *buf, size_t bufsz)
+{
+ int i;
+ float cpu_freq = -1.0;
+ size_t setsize = CPU_ALLOC_SIZE(maxcpus);
+
+ if (desc->present) {
+ for (i = 0; i < desc->ncpuspos; i++) {
+ if (CPU_ISSET_S(real_cpu_num(desc, i), setsize, desc->present)
+ && desc->minmhz[i]) {
+ float freq = atof(desc->minmhz[i]);
+
+ if (cpu_freq < 0.0 || freq < cpu_freq)
+ cpu_freq = freq;
+ }
+ }
+ }
+ snprintf(buf, bufsz, "%.4f", cpu_freq);
+ return buf;
+}
+
static void
read_max_mhz(struct lscpu_desc *desc, int idx)
{
@@ -1898,9 +1944,9 @@ print_summary(struct lscpu_desc *desc, struct lscpu_modifier *mod)
if (desc->static_mhz)
print_s(_("CPU static MHz:"), desc->static_mhz);
if (desc->maxmhz && desc->maxmhz[0])
- print_s(_("CPU max MHz:"), desc->maxmhz[0]);
+ print_s(_("CPU max MHz:"), cpu_max_mhz(desc, buf, sizeof(buf)));
if (desc->minmhz && desc->minmhz[0])
- print_s(_("CPU min MHz:"), desc->minmhz[0]);
+ print_s(_("CPU min MHz:"), cpu_min_mhz(desc, buf, sizeof(buf)));
if (desc->bogomips)
print_s(_("BogoMIPS:"), desc->bogomips);
if (desc->virtflag) {
--
2.14.4

253
SOURCES/0170-chcpu-cleanup-return-codes.patch

@ -0,0 +1,253 @@ @@ -0,0 +1,253 @@
From 8f57ecb12194a10f3dbe6eca9f4bf0b18c4be757 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 5 Mar 2014 11:06:59 +0100
Subject: [PATCH 170/173] chcpu: cleanup return codes

The code currently always return EXIT_SUCCESS, that's strange. It
seems better to return 0 on success, 1 on complete failure and 64 on
partial success.

Signed-off-by: Karel Zak <kzak@redhat.com>
Upstream: http://github.com/karelzak/util-linux/commit/48fc00c1c70f3dbbd8ad6ef423bbba27dd3efb69
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1579439
---
sys-utils/chcpu.8 | 14 ++++++++++
sys-utils/chcpu.c | 82 ++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/sys-utils/chcpu.8 b/sys-utils/chcpu.8
index d016b86f2..125d9d2ad 100644
--- a/sys-utils/chcpu.8
+++ b/sys-utils/chcpu.8
@@ -80,6 +80,20 @@ Display help information and exit.
.TP
.BR \-V , " \-\-version"
Display version information and exit.
+
+.SH RETURN CODES
+.B chcpu
+has the following return codes:
+.TP
+.BR 0
+success
+.TP
+.BR 1
+failure
+.TP
+.BR 64
+partial success
+.RE
.SH AUTHOR
.MT heiko.carstens@de.ibm.com
Heiko Carstens
diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
index 1162888d5..304b80d7a 100644
--- a/sys-utils/chcpu.c
+++ b/sys-utils/chcpu.c
@@ -45,6 +45,9 @@
#define EXCL_ERROR "--{configure,deconfigure,disable,dispatch,enable}"
+/* partial success, otherwise we return regular EXIT_{SUCCESS,FAILURE} */
+#define CHCPU_EXIT_SOMEOK 64
+
#define _PATH_SYS_CPU "/sys/devices/system/cpu"
#define _PATH_SYS_CPU_ONLINE _PATH_SYS_CPU "/online"
#define _PATH_SYS_CPU_RESCAN _PATH_SYS_CPU "/rescan"
@@ -66,21 +69,28 @@ enum {
CMD_CPU_DISPATCH_VERTICAL,
};
+/* returns: 0 = success
+ * < 0 = failure
+ * > 0 = partial success
+ */
static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
{
unsigned int cpu;
int online, rc;
int configured = -1;
+ size_t fails = 0;
for (cpu = 0; cpu < setsize; cpu++) {
if (!CPU_ISSET(cpu, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
printf(_("CPU %d does not exist\n"), cpu);
+ fails++;
continue;
}
if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
printf(_("CPU %d is not hot pluggable\n"), cpu);
+ fails++;
continue;
}
online = path_read_s32(_PATH_SYS_CPU "/cpu%d/online", cpu);
@@ -96,30 +106,35 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
configured = path_read_s32(_PATH_SYS_CPU "/cpu%d/configure", cpu);
if (enable) {
rc = path_write_str("1", _PATH_SYS_CPU "/cpu%d/online", cpu);
- if ((rc == -1) && (configured == 0))
+ if ((rc == -1) && (configured == 0)) {
warnx(_("CPU %d enable failed "
"(CPU is deconfigured)"), cpu);
- else if (rc == -1)
+ fails++;
+ } else if (rc == -1) {
warn(_("CPU %d enable failed"), cpu);
- else
+ fails++;
+ } else
printf(_("CPU %d enabled\n"), cpu);
} else {
if (onlinecpus && num_online_cpus() == 1) {
printf(_("CPU %d disable failed "
"(last enabled CPU)\n"), cpu);
+ fails++;
continue;
}
rc = path_write_str("0", _PATH_SYS_CPU "/cpu%d/online", cpu);
- if (rc == -1)
+ if (rc == -1) {
warn(_("CPU %d disable failed"), cpu);
- else {
+ fails++;
+ } else {
printf(_("CPU %d disabled\n"), cpu);
if (onlinecpus)
CPU_CLR(cpu, onlinecpus);
}
}
}
- return EXIT_SUCCESS;
+
+ return fails == 0 ? 0 : fails == setsize ? -1 : 1;
}
static int cpu_rescan(void)
@@ -129,7 +144,7 @@ static int cpu_rescan(void)
if (path_write_str("1", _PATH_SYS_CPU_RESCAN) == -1)
err(EXIT_FAILURE, _("Failed to trigger rescan of CPUs"));
printf(_("Triggered rescan of CPUs\n"));
- return EXIT_SUCCESS;
+ return 0;
}
static int cpu_set_dispatch(int mode)
@@ -146,23 +161,30 @@ static int cpu_set_dispatch(int mode)
err(EXIT_FAILURE, _("Failed to set vertical dispatch mode"));
printf(_("Successfully set vertical dispatching mode\n"));
}
- return EXIT_SUCCESS;
+ return 0;
}
+/* returns: 0 = success
+ * < 0 = failure
+ * > 0 = partial success
+ */
static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
{
unsigned int cpu;
int rc, current;
+ size_t fails = 0;
for (cpu = 0; cpu < setsize; cpu++) {
if (!CPU_ISSET(cpu, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
printf(_("CPU %d does not exist\n"), cpu);
+ fails++;
continue;
}
if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) {
printf(_("CPU %d is not configurable\n"), cpu);
+ fails++;
continue;
}
current = path_read_s32(_PATH_SYS_CPU "/cpu%d/configure", cpu);
@@ -178,23 +200,27 @@ static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
is_cpu_online(cpu)) {
printf(_("CPU %d deconfigure failed "
"(CPU is enabled)\n"), cpu);
+ fails++;
continue;
}
if (configure) {
rc = path_write_str("1", _PATH_SYS_CPU "/cpu%d/configure", cpu);
- if (rc == -1)
+ if (rc == -1) {
warn(_("CPU %d configure failed"), cpu);
- else
+ fails++;
+ } else
printf(_("CPU %d configured\n"), cpu);
} else {
rc = path_write_str("0", _PATH_SYS_CPU "/cpu%d/configure", cpu);
- if (rc == -1)
+ if (rc == -1) {
warn(_("CPU %d deconfigure failed"), cpu);
- else
+ fails++;
+ } else
printf(_("CPU %d deconfigured\n"), cpu);
}
}
- return EXIT_SUCCESS;
+
+ return fails == 0 ? 0 : fails == setsize ? -1 : 1;
}
static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize)
@@ -233,7 +259,7 @@ int main(int argc, char *argv[])
cpu_set_t *cpu_set;
size_t setsize;
int cmd = -1;
- int c;
+ int c, rc;
static const struct option longopts[] = {
{ "configure", required_argument, 0, 'c' },
@@ -317,19 +343,31 @@ int main(int argc, char *argv[])
switch (cmd) {
case CMD_CPU_ENABLE:
- return cpu_enable(cpu_set, maxcpus, 1);
+ rc = cpu_enable(cpu_set, maxcpus, 1);
+ break;
case CMD_CPU_DISABLE:
- return cpu_enable(cpu_set, maxcpus, 0);
+ rc = cpu_enable(cpu_set, maxcpus, 0);
+ break;
case CMD_CPU_CONFIGURE:
- return cpu_configure(cpu_set, maxcpus, 1);
+ rc = cpu_configure(cpu_set, maxcpus, 1);
+ break;
case CMD_CPU_DECONFIGURE:
- return cpu_configure(cpu_set, maxcpus, 0);
+ rc = cpu_configure(cpu_set, maxcpus, 0);
+ break;
case CMD_CPU_RESCAN:
- return cpu_rescan();
+ rc = cpu_rescan();
+ break;
case CMD_CPU_DISPATCH_HORIZONTAL:
- return cpu_set_dispatch(0);
+ rc = cpu_set_dispatch(0);
+ break;
case CMD_CPU_DISPATCH_VERTICAL:
- return cpu_set_dispatch(1);
+ rc = cpu_set_dispatch(1);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
}
- return EXIT_SUCCESS;
+
+ return rc == 0 ? EXIT_SUCCESS :
+ rc < 0 ? EXIT_FAILURE : CHCPU_EXIT_SOMEOK;
}
--
2.14.4

79
SOURCES/0171-chcpu-cleanup-stdout-stderr-usage.patch

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
From 26c75797103da70f85a5fdd646625edb3eaa300c Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Wed, 5 Mar 2014 11:23:16 +0100
Subject: [PATCH 171/173] chcpu: cleanup stdout/stderr usage

Signed-off-by: Karel Zak <kzak@redhat.com>
Upstream: http://github.com/karelzak/util-linux/commit/69e74525bb3212944feebc8c2848317e04d95ec0
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1579439
---
sys-utils/chcpu.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
index 304b80d7a..ada0eaacc 100644
--- a/sys-utils/chcpu.c
+++ b/sys-utils/chcpu.c
@@ -84,12 +84,12 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
if (!CPU_ISSET(cpu, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
- printf(_("CPU %d does not exist\n"), cpu);
+ warnx(_("CPU %d does not exist"), cpu);
fails++;
continue;
}
if (!path_exist(_PATH_SYS_CPU "/cpu%d/online", cpu)) {
- printf(_("CPU %d is not hot pluggable\n"), cpu);
+ warnx(_("CPU %d is not hot pluggable"), cpu);
fails++;
continue;
}
@@ -107,8 +107,7 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
if (enable) {
rc = path_write_str("1", _PATH_SYS_CPU "/cpu%d/online", cpu);
if ((rc == -1) && (configured == 0)) {
- warnx(_("CPU %d enable failed "
- "(CPU is deconfigured)"), cpu);
+ warn(_("CPU %d enable failed (CPU is deconfigured)"), cpu);
fails++;
} else if (rc == -1) {
warn(_("CPU %d enable failed"), cpu);
@@ -117,8 +116,7 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
printf(_("CPU %d enabled\n"), cpu);
} else {
if (onlinecpus && num_online_cpus() == 1) {
- printf(_("CPU %d disable failed "
- "(last enabled CPU)\n"), cpu);
+ warnx(_("CPU %d disable failed (last enabled CPU)"), cpu);
fails++;
continue;
}
@@ -178,12 +176,12 @@ static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
if (!CPU_ISSET(cpu, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
- printf(_("CPU %d does not exist\n"), cpu);
+ warnx(_("CPU %d does not exist"), cpu);
fails++;
continue;
}
if (!path_exist(_PATH_SYS_CPU "/cpu%d/configure", cpu)) {
- printf(_("CPU %d is not configurable\n"), cpu);
+ warnx(_("CPU %d is not configurable"), cpu);
fails++;
continue;
}
@@ -198,8 +196,7 @@ static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
}
if ((current == 1) && (configure == 0) && onlinecpus &&
is_cpu_online(cpu)) {
- printf(_("CPU %d deconfigure failed "
- "(CPU is enabled)\n"), cpu);
+ warnx(_("CPU %d deconfigure failed (CPU is enabled)"), cpu);
fails++;
continue;
}
--
2.14.4

86
SOURCES/0172-lscpu-chcpu-Avoid-use-of-the-old-CPU-macros.patch

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
From 255a3b8bb8cbcb3f689cc3332983983bfbf9eca0 Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Wed, 9 May 2018 18:08:32 +0200
Subject: [PATCH 172/173] lscpu, chcpu: Avoid use of the old CPU macros

The old CPU macros are limited to 1024 cores. As a result, lscpu cannot
count sockets on large systems. Use new scalable macros.

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
Cc: Michael Matz <matz@suse.de>
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1579439
Upstream: http://github.com/karelzak/util-linux/commit/538b50cb0a4aac56b6b3b6e4d1e8ce886854c6d8
---
sys-utils/chcpu.c | 6 +++---
sys-utils/lscpu.c | 7 +++++--
2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
index ada0eaacc..7843dfb22 100644
--- a/sys-utils/chcpu.c
+++ b/sys-utils/chcpu.c
@@ -81,7 +81,7 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
size_t fails = 0;
for (cpu = 0; cpu < setsize; cpu++) {
- if (!CPU_ISSET(cpu, cpu_set))
+ if (!CPU_ISSET_S(cpu, setsize, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
warnx(_("CPU %d does not exist"), cpu);
@@ -127,7 +127,7 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
} else {
printf(_("CPU %d disabled\n"), cpu);
if (onlinecpus)
- CPU_CLR(cpu, onlinecpus);
+ CPU_CLR_S(cpu, setsize, onlinecpus);
}
}
}
@@ -173,7 +173,7 @@ static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
size_t fails = 0;
for (cpu = 0; cpu < setsize; cpu++) {
- if (!CPU_ISSET(cpu, cpu_set))
+ if (!CPU_ISSET_S(cpu, setsize, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
warnx(_("CPU %d does not exist"), cpu);
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 4c15de1d4..002ad0d1c 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -626,7 +626,7 @@ read_basicinfo(struct lscpu_desc *desc, struct lscpu_modifier *mod)
desc->idx2cpunum = xcalloc(desc->ncpuspos, sizeof(int));
for (num = 0, idx = 0; num < maxcpus; num++) {
- if (CPU_ISSET(num, tmp))
+ if (CPU_ISSET_S(num, setsize, tmp))
desc->idx2cpunum[idx++] = num;
}
cpuset_free(tmp);
@@ -2038,6 +2038,7 @@ int main(int argc, char *argv[])
int c, i;
int columns[ARRAY_SIZE(coldescs)], ncolumns = 0;
int cpu_modifier_specified = 0;
+ size_t setsize;
static const struct option longopts[] = {
{ "all", no_argument, NULL, 'a' },
@@ -2134,10 +2135,12 @@ int main(int argc, char *argv[])
read_basicinfo(desc, mod);
+ setsize = CPU_ALLOC_SIZE(maxcpus);
+
for (i = 0; i < desc->ncpuspos; i++) {
/* only consider present CPUs */
if (desc->present &&
- !CPU_ISSET(real_cpu_num(desc, i), desc->present))
+ !CPU_ISSET_S(real_cpu_num(desc, i), setsize, desc->present))
continue;
read_topology(desc, i);
read_cache(desc, i);
--
2.14.4

74
SOURCES/0173-chcpu-Fix-maximal-number-of-CPUs.patch

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
From 72e09b02e7b4cf3e9e77ef02d5073d9a11f3b314 Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <sbrabec@suse.cz>
Date: Wed, 9 May 2018 22:13:07 +0200
Subject: [PATCH 173/173] chcpu: Fix maximal number of CPUs

chcpu.c mixed maxcpus (number of cpus) and setsize (size of CPU bit
mask). It effectively limits number of CPUs to 1/8 of the supported
amount.

Signed-off-by: Stanislav Brabec <sbrabec@suse.cz>
Cc: Michael Matz <matz@suse.de>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Upstream: http://github.com/karelzak/util-linux/commit/607274943bfd3d4856b872bc4278b36903fb2182
Addresses: http://bugzilla.redhat.com/show_bug.cgi?id=1579439
---
sys-utils/chcpu.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sys-utils/chcpu.c b/sys-utils/chcpu.c
index 7843dfb22..1a0157360 100644
--- a/sys-utils/chcpu.c
+++ b/sys-utils/chcpu.c
@@ -75,12 +75,12 @@ enum {
*/
static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
{
- unsigned int cpu;
+ int cpu;
int online, rc;
int configured = -1;
- size_t fails = 0;
+ int fails = 0;
- for (cpu = 0; cpu < setsize; cpu++) {
+ for (cpu = 0; cpu < maxcpus; cpu++) {
if (!CPU_ISSET_S(cpu, setsize, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
@@ -132,7 +132,7 @@ static int cpu_enable(cpu_set_t *cpu_set, size_t setsize, int enable)
}
}
- return fails == 0 ? 0 : fails == setsize ? -1 : 1;
+ return fails == 0 ? 0 : fails == maxcpus ? -1 : 1;
}
static int cpu_rescan(void)
@@ -168,11 +168,11 @@ static int cpu_set_dispatch(int mode)
*/
static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
{
- unsigned int cpu;
+ int cpu;
int rc, current;
- size_t fails = 0;
+ int fails = 0;
- for (cpu = 0; cpu < setsize; cpu++) {
+ for (cpu = 0; cpu < maxcpus; cpu++) {
if (!CPU_ISSET_S(cpu, setsize, cpu_set))
continue;
if (!path_exist(_PATH_SYS_CPU "/cpu%d", cpu)) {
@@ -217,7 +217,7 @@ static int cpu_configure(cpu_set_t *cpu_set, size_t setsize, int configure)
}
}
- return fails == 0 ? 0 : fails == setsize ? -1 : 1;
+ return fails == 0 ? 0 : fails == maxcpus ? -1 : 1;
}
static void cpu_parse(char *cpu_string, cpu_set_t *cpu_set, size_t setsize)
--
2.14.4

44
SOURCES/0174-libblkid-minix-Match-minix-superblock-types.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
From b4d5cf4819023ce07ecd39729cdd4cde8b59ca35 Mon Sep 17 00:00:00 2001
From: Nate Clark <nate@neworld.us>
Date: Wed, 4 Jan 2017 15:24:22 -0500
Subject: [PATCH 174/176] libblkid/minix: Match minix superblock types

All of the types in the minix super block are unsigned but in
probe_minix they were being treated as signed. This would cause some of
the extra sanity checks to pass on a non minix device. The types were
updated to match the return types of the helper functions in
disk-utils/minix_programs.h

This can be checked by creating a swap partition with one of these UUIDs
35f1f264-2468-471a-bc85-acc9f4bc04a3
35f1f264-6824-471a-bc85-acc9f4bc04a3
35f1f264-2478-471a-bc85-acc9f4bc04a3
35f1f264-7824-471a-bc85-acc9f4bc04a3

Prior to this change they would all be considered minix and swap by
blkid.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1594681
Upstream: http://github.com/karelzak/util-linux/commit/a9975c1072c4975ec2df958188a80d89cabc6171
Signed-off-by: Nate Clark <nate@neworld.us>
---
libblkid/src/superblocks/minix.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libblkid/src/superblocks/minix.c b/libblkid/src/superblocks/minix.c
index 3e80e5b22..a20d51f2c 100644
--- a/libblkid/src/superblocks/minix.c
+++ b/libblkid/src/superblocks/minix.c
@@ -87,7 +87,8 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
if (version <= 2) {
struct minix_super_block *sb = (struct minix_super_block *) data;
- int zones, ninodes, imaps, zmaps, firstz;
+ unsigned long zones, ninodes, imaps, zmaps;
+ off_t firstz;
if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
return 1;
--
2.14.4

44
SOURCES/0175-libblkid-minix-Sanity-check-superblock-s_state-for-v.patch

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
From 6eb3a6579768458c13c26958e1cc3fbffe2ada70 Mon Sep 17 00:00:00 2001
From: Nate Clark <nate@neworld.us>
Date: Wed, 4 Jan 2017 15:21:17 -0500
Subject: [PATCH 175/176] libblkid/minix: Sanity check superblock s_state for v
1 and 2

Swap devices with specific values in the uuid can look like minix
devices to blkid. Add an extra check to make sure the state of the
filesystem has valid state flags.

A couple of offending swap uuids include:
35f1f264-137f-471a-bc85-acc9f4bc04a3
35f1f264-7f13-471a-bc85-acc9f4bc04a3
35f1f264-138f-471a-bc85-acc9f4bc04a3
35f1f264-8f13-471a-bc85-acc9f4bc04a3

Without this change a swap device with any of those uuids would be
detected as minix and swap by blkid.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1594681
Upstream: http://github.com/karelzak/util-linux/commit/892553b1a41b449f58462f123eca2bf2c6c56b33
Signed-off-by: Nate Clark <nate@neworld.us>
---
libblkid/src/superblocks/minix.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/libblkid/src/superblocks/minix.c b/libblkid/src/superblocks/minix.c
index a20d51f2c..4e70fda8f 100644
--- a/libblkid/src/superblocks/minix.c
+++ b/libblkid/src/superblocks/minix.c
@@ -93,6 +93,10 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
return 1;
+ uint16_t state = minix_swab16(swabme, sb->s_state);
+ if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
+ return 1;
+
zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
minix_swab16(swabme, sb->s_nzones);
ninodes = minix_swab16(swabme, sb->s_ninodes);
--
2.14.4

90
SOURCES/0176-libblkid-minix-Use-same-checks-for-version-3.patch

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
From b5d9bfe34e62cf1c57646efa0bd72ecad7d98258 Mon Sep 17 00:00:00 2001
From: Nate Clark <nate@neworld.us>
Date: Wed, 4 Jan 2017 15:24:32 -0500
Subject: [PATCH 176/176] libblkid/minix: Use same checks for version 3

fsck.minix performs the same sanity checks on all versions of the
superblock. Update the probe to perform the same sanity checks so it is
less likely a different type of filesystem will be identified as minix.

Upstream: http://github.com/karelzak/util-linux/commit/f82c804869bb8613fa0924e3111b7eb55bb04fcd
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1594681
Signed-off-by: Nate Clark <nate@neworld.us>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libblkid/src/superblocks/minix.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/libblkid/src/superblocks/minix.c b/libblkid/src/superblocks/minix.c
index 4e70fda8f..21b3bf8bb 100644
--- a/libblkid/src/superblocks/minix.c
+++ b/libblkid/src/superblocks/minix.c
@@ -75,6 +75,9 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
unsigned char *ext;
const unsigned char *data;
int version = 0, swabme = 0;
+ unsigned long zones, ninodes, imaps, zmaps;
+ off_t firstz;
+ size_t zone_size;
data = blkid_probe_get_buffer(pr, 1024,
max(sizeof(struct minix_super_block),
@@ -85,14 +88,9 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
if (version < 1)
return 1;
+
if (version <= 2) {
struct minix_super_block *sb = (struct minix_super_block *) data;
- unsigned long zones, ninodes, imaps, zmaps;
- off_t firstz;
-
- if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
- return 1;
-
uint16_t state = minix_swab16(swabme, sb->s_state);
if ((state & (MINIX_VALID_FS | MINIX_ERROR_FS)) != state)
return 1;
@@ -103,20 +101,30 @@ static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
imaps = minix_swab16(swabme, sb->s_imap_blocks);
zmaps = minix_swab16(swabme, sb->s_zmap_blocks);
firstz = minix_swab16(swabme, sb->s_firstdatazone);
-
- /* sanity checks to be sure that the FS is really minix */
- if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
- return 1;
- if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
- return 1;
-
+ zone_size = sb->s_log_zone_size;
} else if (version == 3) {
struct minix3_super_block *sb = (struct minix3_super_block *) data;
- if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
- return 1;
+ zones = minix_swab32(swabme, sb->s_zones);
+ ninodes = minix_swab32(swabme, sb->s_ninodes);
+ imaps = minix_swab16(swabme, sb->s_imap_blocks);
+ zmaps = minix_swab16(swabme, sb->s_zmap_blocks);
+ firstz = minix_swab16(swabme, sb->s_firstdatazone);
+ zone_size = sb->s_log_zone_size;
}
+ /* sanity checks to be sure that the FS is really minix.
+ * see disk-utils/fsck.minix.c read_superblock
+ */
+ if (zone_size != 0 || ninodes == 0 || ninodes == UINT32_MAX)
+ return 1;
+ if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
+ return 1;
+ if (firstz > (off_t) zones)
+ return 1;
+ if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
+ return 1;
+
/* unfortunately, some parts of ext3 is sometimes possible to
* interpreted as minix superblock. So check for extN magic
* string. (For extN magic string and offsets see ext.c.)
--
2.14.4

41
SOURCES/0177-mount-append-inverting-options-for-mount.-type-on-us.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
From 4b376d1ad1b46408bc59d949c277991a9b5035eb Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 27 Oct 2016 15:30:20 +0200
Subject: [PATCH 177/178] mount: append inverting options for mount.<type> on
"users"

If you call mount(8) as root, then we need to append inverting options
(if specified by fstab) for "user" and "users" to /sbin/mount.<type>
command line, because for UID=0 mount.nfs follows command line rather
than the fstab setting.

This has been originally implemented by commit
a4c0cc75ff9744299f108c259efab1bd30c8007a for the old mount(8). The
same feature is supported by libmount, unfortunately for "user" only.
We need the same also for "users" to be backwardly compatible.

Addresses: https://github.com/karelzak/util-linux/issues/368
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1618711
Upstream: http://github.com/karelzak/util-linux/commit/3c4a3de0fcb8f21bffacfd8bdc3d6fbd683c71f5
Signed-off-by: Karel Zak <kzak@redhat.com>
---
libmount/src/context_mount.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libmount/src/context_mount.c b/libmount/src/context_mount.c
index 4df2646b0..0f4485592 100644
--- a/libmount/src/context_mount.c
+++ b/libmount/src/context_mount.c
@@ -321,7 +321,8 @@ static int generate_helper_optstr(struct libmnt_context *cxt, char **optstr)
if (!*optstr)
return -ENOMEM;
- if (cxt->user_mountflags & MNT_MS_USER) {
+ if ((cxt->user_mountflags & MNT_MS_USER) ||
+ (cxt->user_mountflags & MNT_MS_USERS)) {
/*
* This is unnecessary for real user-mounts as mount.<type>
* helpers have to always follow fstab rather than mount
--
2.14.4

839
SOURCES/0178-sulogin-backport-RHEL-8-version.patch

@ -0,0 +1,839 @@ @@ -0,0 +1,839 @@
From f720781671c9f5421fb8101dd3bcf7b56efca131 Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Mon, 20 Aug 2018 14:56:08 +0200
Subject: [PATCH 178/178] sulogin: backport RHEL-8 version

The new version is more robust and it does not use mmap()-ed shared
memory between sulogins instances. It also provides some fallbacks for
s390 machines.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1616264
Signed-off-by: Karel Zak <kzak@redhat.com>
---
configure.ac | 1 +
include/c.h | 4 +
login-utils/sulogin-consoles.c | 116 +++++++++++++------
login-utils/sulogin.c | 253 +++++++++++++++++++++++++++--------------
4 files changed, 252 insertions(+), 122 deletions(-)

diff --git a/configure.ac b/configure.ac
index d561e01d0..3f07df495 100644
--- a/configure.ac
+++ b/configure.ac
@@ -218,6 +218,7 @@ AC_CHECK_HEADERS([ \
sys/prctl.h \
sys/queue.h \
sys/resource.h \
+ sys/sysmacros.h \
sys/socket.h \
sys/sockio.h \
sys/stat.h \
diff --git a/include/c.h b/include/c.h
index 124035ea5..51d439297 100644
--- a/include/c.h
+++ b/include/c.h
@@ -19,6 +19,10 @@
# include <err.h>
#endif
+#ifdef HAVE_SYS_SYSMACROS_H
+# include <sys/sysmacros.h> /* for major, minor */
+#endif
+
#ifndef HAVE_USLEEP
# include <time.h>
#endif
diff --git a/login-utils/sulogin-consoles.c b/login-utils/sulogin-consoles.c
index 07af33a6d..2c0eed3a4 100644
--- a/login-utils/sulogin-consoles.c
+++ b/login-utils/sulogin-consoles.c
@@ -36,8 +36,9 @@
# include <linux/serial.h>
# include <linux/major.h>
#endif
-#include <fcntl.h>
#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#ifdef USE_SULOGIN_EMERGENCY_MOUNT
@@ -74,7 +75,7 @@ static int consoles_debug;
} while (0)
static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
-dbgprint(const char *mesg, ...)
+dbgprint(const char * const mesg, ...)
{
va_list ap;
va_start(ap, mesg);
@@ -112,7 +113,7 @@ void emergency_do_mounts(void)
}
if (stat("/", &rt) != 0) {
- warn("can not get file status of root file system\n");
+ warn("cannot get file status of root file system\n");
return;
}
@@ -150,17 +151,19 @@ void emergency_do_mounts(void) { }
* the caller has to free the result
*/
static __attribute__((__nonnull__))
-char *oneline(const char *file)
+char *oneline(const char * const file)
{
FILE *fp;
char *ret = NULL;
- size_t len = 0;
+ size_t dummy = 0;
+ ssize_t len;
DBG(dbgprint("reading %s", file));
- if (!(fp = fopen(file, "re")))
+ if (!(fp = fopen(file, "r" UL_CLOEXECSTR)))
return NULL;
- if (getline(&ret, &len, fp) >= 0) {
+ len = getline(&ret, &dummy, fp);
+ if (len >= 0) {
char *nl;
if (len)
@@ -179,7 +182,7 @@ char *oneline(const char *file)
* /sys/class/tty, the caller has to free the result.
*/
static __attribute__((__malloc__))
-char *actattr(const char *tty)
+char *actattr(const char * const tty)
{
char *ret, *path;
@@ -198,7 +201,7 @@ char *actattr(const char *tty)
* /sys/class/tty.
*/
static
-dev_t devattr(const char *tty)
+dev_t devattr(const char * const tty)
{
dev_t dev = 0;
char *path, *value;
@@ -223,42 +226,77 @@ dev_t devattr(const char *tty)
#endif /* __linux__ */
/*
- * Search below /dev for the characer device in `dev_t comparedev' variable.
+ * Search below /dev for the character device in `dev_t comparedev' variable.
+ * Note that realpath(3) is used here to avoid not existent devices due the
+ * strdup(3) used in our canonicalize_path()!
*/
static
#ifdef __GNUC__
__attribute__((__nonnull__,__malloc__,__hot__))
#endif
-char* scandev(DIR *dir, dev_t comparedev)
+char* scandev(DIR *dir, const dev_t comparedev)
{
+ char path[PATH_MAX];
char *name = NULL;
- struct dirent *dent;
- int fd;
+ const struct dirent *dent;
+ int len, fd;
DBG(dbgprint("scanning /dev for %u:%u", major(comparedev), minor(comparedev)));
+ /*
+ * Try udev links on character devices first.
+ */
+ if ((len = snprintf(path, sizeof(path),
+ "/dev/char/%u:%u", major(comparedev), minor(comparedev))) > 0 &&
+ (size_t)len < sizeof(path)) {
+
+ name = realpath(path, NULL);
+ if (name)
+ goto out;
+ }
+
fd = dirfd(dir);
rewinddir(dir);
while ((dent = readdir(dir))) {
- char path[PATH_MAX];
struct stat st;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ if (dent->d_type != DT_UNKNOWN && dent->d_type != DT_CHR)
+ continue;
+#endif
if (fstatat(fd, dent->d_name, &st, 0) < 0)
continue;
if (!S_ISCHR(st.st_mode))
continue;
if (comparedev != st.st_rdev)
continue;
- if ((size_t)snprintf(path, sizeof(path), "/dev/%s", dent->d_name) >= sizeof(path))
+ if ((len = snprintf(path, sizeof(path), "/dev/%s", dent->d_name)) < 0 ||
+ (size_t)len >= sizeof(path))
continue;
-#ifdef USE_SULOGIN_EMERGENCY_MOUNT
- if (emergency_flags & MNT_DEVTMPFS)
- mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev);
-#endif
- name = canonicalize_path(path);
- break;
+ name = realpath(path, NULL);
+ if (name)
+ goto out;
}
+#ifdef USE_SULOGIN_EMERGENCY_MOUNT
+ /*
+ * There was no /dev mounted hence and no device was found hence we create our own.
+ */
+ if (!name && (emergency_flags & MNT_DEVTMPFS)) {
+
+ if ((len = snprintf(path, sizeof(path),
+ "/dev/tmp-%u:%u", major(comparedev), minor(comparedev))) < 0 ||
+ (size_t)len >= sizeof(path))
+ goto out;
+
+ if (mknod(path, S_IFCHR|S_IRUSR|S_IWUSR, comparedev) < 0 && errno != EEXIST)
+ goto out;
+
+ name = realpath(path, NULL);
+ }
+#endif
+out:
return name;
}
@@ -273,12 +311,12 @@ char* scandev(DIR *dir, dev_t comparedev)
*/
static
#ifdef __GNUC__
-__attribute__((__nonnull__,__hot__))
+__attribute__((__hot__))
#endif
-int append_console(struct list_head *consoles, const char *name)
+int append_console(struct list_head *consoles, const char * const name)
{
struct console *restrict tail;
- struct console *last = NULL;
+ const struct console *last = NULL;
DBG(dbgprint("appenging %s", name));
@@ -300,7 +338,7 @@ int append_console(struct list_head *consoles, const char *name)
tail->flags = 0;
tail->fd = -1;
tail->id = last ? last->id + 1 : 0;
- tail->pid = 0;
+ tail->pid = -1;
memset(&tail->tio, 0, sizeof(tail->tio));
return 0;
@@ -319,11 +357,11 @@ static int detect_consoles_from_proc(struct list_head *consoles)
char fbuf[16 + 1];
DIR *dir = NULL;
FILE *fc = NULL;
- int maj, min, rc = 1;
+ int maj, min, rc = 1, matches;
DBG(dbgprint("trying /proc"));
- fc = fopen("/proc/consoles", "re");
+ fc = fopen("/proc/consoles", "r" UL_CLOEXECSTR);
if (!fc) {
rc = 2;
goto done;
@@ -332,10 +370,12 @@ static int detect_consoles_from_proc(struct list_head *consoles)
if (!dir)
goto done;
- while (fscanf(fc, "%*s %*s (%16[^)]) %d:%d", fbuf, &maj, &min) == 3) {
+ while ((matches = fscanf(fc, "%*s %*s (%16[^)]) %d:%d", fbuf, &maj, &min)) >= 1) {
char *name;
dev_t comparedev;
+ if (matches != 3)
+ continue;
if (!strchr(fbuf, 'E'))
continue;
comparedev = makedev(maj, min);
@@ -509,7 +549,7 @@ done:
#ifdef TIOCGDEV
static int detect_consoles_from_tiocgdev(struct list_head *consoles,
- int fallback,
+ const int fallback,
const char *device)
{
unsigned int devnum;
@@ -579,7 +619,7 @@ done:
* Returns 1 if stdout and stderr should be reconnected and 0
* otherwise or less than zero on error.
*/
-int detect_consoles(const char *device, int fallback, struct list_head *consoles)
+int detect_consoles(const char *device, const int fallback, struct list_head *consoles)
{
int fd, reconnect = 0, rc;
dev_t comparedev = 0;
@@ -587,7 +627,7 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
consoles_debug = getenv("CONSOLES_DEBUG") ? 1 : 0;
if (!device || !*device)
- fd = dup(fallback);
+ fd = fallback >= 0 ? dup(fallback) : - 1;
else {
fd = open(device, O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
reconnect = 1;
@@ -602,6 +642,14 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
struct stat st;
#ifdef TIOCGDEV
unsigned int devnum;
+#endif
+#ifdef __GNU__
+ /*
+ * The Hurd always gives st_rdev as 0, which causes this
+ * method to select the first terminal it finds.
+ */
+ close(fd);
+ goto fallback;
#endif
DBG(dbgprint("trying device/fallback file descriptor"));
@@ -670,7 +718,7 @@ int detect_consoles(const char *device, int fallback, struct list_head *consoles
#ifdef __linux__
console:
/*
- * Detection of devices used for Linux system consolei using
+ * Detection of devices used for Linux system console using
* the /proc/consoles API with kernel 2.6.38 and higher.
*/
rc = detect_consoles_from_proc(consoles);
@@ -754,8 +802,7 @@ int main(int argc, char *argv[])
{
char *name = NULL;
int fd, re;
- LIST_HEAD(consoles);
- struct list_head *p;
+ struct list_head *p, consoles;
if (argc == 2) {
name = argv[1];
@@ -768,6 +815,7 @@ int main(int argc, char *argv[])
if (!name)
errx(EXIT_FAILURE, "usage: %s [<tty>]\n", program_invocation_short_name);
+ INIT_LIST_HEAD(&consoles);
re = detect_consoles(name, fd, &consoles);
list_for_each(p, &consoles) {
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index dd73a1c50..4620ed2da 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -56,8 +56,12 @@
#include "c.h"
#include "closestream.h"
+#include "env.h"
#include "nls.h"
#include "pathnames.h"
+#ifdef USE_PLYMOUTH_SUPPORT
+# include "plymouth-ctrl.h"
+#endif
#include "strutils.h"
#include "ttyutils.h"
#include "sulogin-consoles.h"
@@ -66,13 +70,12 @@
static unsigned int timeout;
static int profile;
static volatile uint32_t openfd; /* Remember higher file descriptors */
-static volatile uint32_t *usemask;
-struct sigaction saved_sigint;
-struct sigaction saved_sigtstp;
-struct sigaction saved_sigquit;
-struct sigaction saved_sighup;
-struct sigaction saved_sigchld;
+static struct sigaction saved_sigint;
+static struct sigaction saved_sigtstp;
+static struct sigaction saved_sigquit;
+static struct sigaction saved_sighup;
+static struct sigaction saved_sigchld;
static volatile sig_atomic_t alarm_rised;
static volatile sig_atomic_t sigchild;
@@ -81,7 +84,12 @@ static volatile sig_atomic_t sigchild;
# define IUCLC 0
#endif
-static int locked_account_password(const char *passwd)
+#ifndef WEXITED
+# warning "WEXITED is missing, sulogin may not work as expected"
+# define WEXITED 0
+#endif
+
+static int locked_account_password(const char * const passwd)
{
if (passwd && (*passwd == '*' || *passwd == '!'))
return 1;
@@ -93,10 +101,29 @@ static int locked_account_password(const char *passwd)
*/
static void tcinit(struct console *con)
{
- int mode = 0, flags = 0;
+ int flags = 0, mode = 0;
struct termios *tio = &con->tio;
- int fd = con->fd;
-
+ const int fd = con->fd;
+#ifdef USE_PLYMOUTH_SUPPORT
+ struct termios lock;
+ int i = (plymouth_command(MAGIC_PING)) ? PLYMOUTH_TERMIOS_FLAGS_DELAY : 0;
+ if (i)
+ plymouth_command(MAGIC_QUIT);
+ while (i-- > 0) {
+ /*
+ * With plymouth the termios flags become changed after this
+ * function had changed the termios.
+ */
+ memset(&lock, 0, sizeof(struct termios));
+ if (ioctl(fd, TIOCGLCKTRMIOS, &lock) < 0)
+ break;
+ if (!lock.c_iflag && !lock.c_oflag && !lock.c_cflag && !lock.c_lflag)
+ break;
+ sleep(1);
+ }
+ memset(&lock, 0, sizeof(struct termios));
+ ioctl(fd, TIOCSLCKTRMIOS, &lock);
+#endif
errno = 0;
if (tcgetattr(fd, tio) < 0) {
@@ -189,20 +216,23 @@ setattr:
*/
static void tcfinal(struct console *con)
{
- struct termios *tio;
- int fd;
+ struct termios *tio = &con->tio;
+ const int fd = con->fd;
if ((con->flags & CON_SERIAL) == 0) {
- setenv("TERM", "linux", 1);
+ xsetenv("TERM", "linux", 1);
return;
}
- if (con->flags & CON_NOTTY)
+ if (con->flags & CON_NOTTY) {
+ xsetenv("TERM", "dumb", 1);
return;
+ }
- setenv("TERM", "vt102", 1);
- tio = &con->tio;
- fd = con->fd;
-
+#if defined (__s390__) || defined (__s390x__)
+ xsetenv("TERM", "dumb", 1);
+#else
+ xsetenv("TERM", "vt102", 1);
+#endif
tio->c_iflag |= (IXON | IXOFF);
tio->c_lflag |= (ICANON | ISIG | ECHO|ECHOE|ECHOK|ECHOKE);
tio->c_oflag |= OPOST;
@@ -237,11 +267,11 @@ static void tcfinal(struct console *con)
break;
case 1: /* odd parity */
tio->c_cflag |= PARODD;
- /* fall through */
+ /* fallthrough */
case 2: /* even parity */
tio->c_cflag |= PARENB;
tio->c_iflag |= (INPCK | ISTRIP);
- /* fall through */
+ /* fallthrough */
case (1 | 2): /* no parity bit */
tio->c_cflag &= ~CSIZE;
tio->c_cflag |= CS7;
@@ -466,7 +496,7 @@ static struct passwd *getrootpwent(int try_manually)
warnx(_("%s: no entry for root"), _PATH_SHADOW_PASSWD);
*pwd.pw_passwd = '\0';
}
- /* locked accont passwords are valid too */
+ /* locked account passwords are valid too */
if (!locked_account_password(pwd.pw_passwd) && !valid(pwd.pw_passwd)) {
warnx(_("%s: root password garbled"), _PATH_SHADOW_PASSWD);
*pwd.pw_passwd = '\0';
@@ -524,22 +554,17 @@ err:
*/
static void setup(struct console *con)
{
- pid_t pid, pgrp, ppgrp, ttypgrp;
- int fd;
+ int fd = con->fd;
+ const pid_t pid = getpid(), pgrp = getpgid(0), ppgrp =
+ getpgid(getppid()), ttypgrp = tcgetpgrp(fd);
if (con->flags & CON_NOTTY)
return;
- fd = con->fd;
/*
* Only go through this trouble if the new
* tty doesn't fall in this process group.
*/
- pid = getpid();
- pgrp = getpgid(0);
- ppgrp = getpgid(getppid());
- ttypgrp = tcgetpgrp(fd);
-
if (pgrp != ttypgrp && ppgrp != ttypgrp) {
if (pid != getsid(0)) {
if (pid == getpgid(0))
@@ -575,21 +600,20 @@ static void setup(struct console *con)
* Ask for the password. Note that there is no default timeout as we normally
* skip this during boot.
*/
-static char *getpasswd(struct console *con)
+static const char *getpasswd(struct console *con)
{
struct sigaction sa;
struct termios tty;
static char pass[128], *ptr;
struct chardata *cp;
- char *ret = pass;
+ const char *ret = pass;
unsigned char tc;
char c, ascval;
int eightbit;
- int fd;
+ const int fd = con->fd;
if (con->flags & CON_NOTTY)
goto out;
- fd = con->fd;
cp = &con->cp;
tty = con->tio;
@@ -597,6 +621,7 @@ static char *getpasswd(struct console *con)
tty.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP|ISIG);
tc = (tcsetattr(fd, TCSAFLUSH, &tty) == 0);
+ sigemptyset(&sa.sa_mask);
sa.sa_handler = alrm_handler;
sa.sa_flags = 0;
sigaction(SIGALRM, &sa, NULL);
@@ -615,7 +640,7 @@ static char *getpasswd(struct console *con)
ret = NULL;
goto quit;
}
- usleep(1000);
+ usleep(250000);
continue;
}
ret = (char*)0;
@@ -627,7 +652,7 @@ static char *getpasswd(struct console *con)
case ENOENT:
break;
default:
- warn(_("%s: read failed"), con->tty);
+ warn(_("cannot read %s"), con->tty);
break;
}
goto quit;
@@ -694,8 +719,8 @@ static void sushell(struct passwd *pwd)
{
char shell[PATH_MAX];
char home[PATH_MAX];
- char *p;
- char *su_shell;
+ char const *p;
+ char const *su_shell;
/*
* Set directory and shell.
@@ -731,16 +756,16 @@ static void sushell(struct passwd *pwd)
if (getcwd(home, sizeof(home)) == NULL)
strcpy(home, "/");
- setenv("HOME", home, 1);
- setenv("LOGNAME", "root", 1);
- setenv("USER", "root", 1);
+ xsetenv("HOME", home, 1);
+ xsetenv("LOGNAME", "root", 1);
+ xsetenv("USER", "root", 1);
if (!profile)
- setenv("SHLVL","0",1);
+ xsetenv("SHLVL","0",1);
/*
* Try to execute a shell.
*/
- setenv("SHELL", su_shell, 1);
+ xsetenv("SHELL", su_shell, 1);
unmask_signal(SIGINT, &saved_sigint);
unmask_signal(SIGTSTP, &saved_sigtstp);
unmask_signal(SIGQUIT, &saved_sigquit);
@@ -765,17 +790,21 @@ static void sushell(struct passwd *pwd)
execl(su_shell, shell, NULL);
warn(_("failed to execute %s"), su_shell);
- setenv("SHELL", "/bin/sh", 1);
+ xsetenv("SHELL", "/bin/sh", 1);
execl("/bin/sh", profile ? "-sh" : "sh", NULL);
warn(_("failed to execute %s"), "/bin/sh");
}
-static void usage(FILE *out)
+static void usage(void)
{
+ FILE *out = stdout;
fputs(USAGE_HEADER, out);
fprintf(out, _(
" %s [options] [tty device]\n"), program_invocation_short_name);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Single-user login.\n"), out);
+
fputs(USAGE_OPTIONS, out);
fputs(_(" -p, --login-shell start a login shell\n"
" -t, --timeout <seconds> max time to wait for a password (default: no limit)\n"
@@ -783,32 +812,35 @@ static void usage(FILE *out)
out);
fputs(USAGE_SEPARATOR, out);
- fputs(USAGE_HELP, out);
- fputs(USAGE_VERSION, out);
- fprintf(out, USAGE_MAN_TAIL("sulogin(8)"));
+ printf(USAGE_HELP_OPTIONS(26));
+ printf(USAGE_MAN_TAIL("sulogin(8)"));
}
int main(int argc, char **argv)
{
- LIST_HEAD(consoles);
- struct list_head *ptr;
+ struct list_head *ptr, consoles;
struct console *con;
char *tty = NULL;
struct passwd *pwd;
- int c, status = 0;
- int reconnect = 0;
+ const struct timespec sigwait = { .tv_sec = 0, .tv_nsec = 50000000 };
+ siginfo_t status = { 0 };
+ sigset_t set;
+ int c, reconnect = 0;
int opt_e = 0;
+ int wait = 0;
pid_t pid;
static const struct option longopts[] = {
- { "login-shell", 0, 0, 'p' },
- { "timeout", 1, 0, 't' },
- { "force", 0, 0, 'e' },
- { "help", 0, 0, 'h' },
- { "version", 0, 0, 'V' },
- { NULL, 0, 0, 0 }
+ { "login-shell", no_argument, NULL, 'p' },
+ { "timeout", required_argument, NULL, 't' },
+ { "force", no_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
};
+ INIT_LIST_HEAD(&consoles);
+
/*
* If we are init we need to set up a own session.
*/
@@ -840,17 +872,16 @@ int main(int argc, char **argv)
printf(UTIL_LINUX_VERSION);
return EXIT_SUCCESS;
case 'h':
- usage(stdout);
+ usage();
return EXIT_SUCCESS;
default:
- usage(stderr);
- /* Do not exit! */
+ /* Do not exit! getopt prints a warning. */
break;
}
}
if (geteuid() != 0)
- errx(EXIT_FAILURE, _("only root can run this program."));
+ errx(EXIT_FAILURE, _("only superuser can run this program"));
mask_signal(SIGQUIT, SIG_IGN, &saved_sigquit);
mask_signal(SIGTSTP, SIG_IGN, &saved_sigtstp);
@@ -877,7 +908,7 @@ int main(int argc, char **argv)
reconnect = detect_consoles(tty, STDIN_FILENO, &consoles);
/*
- * If previous stdin was not the speified tty and therefore reconnected
+ * If previous stdin was not the specified tty and therefore reconnected
* to the specified tty also reconnect stdout and stderr.
*/
if (reconnect) {
@@ -900,7 +931,7 @@ int main(int argc, char **argv)
* Get the root password.
*/
if ((pwd = getrootpwent(opt_e)) == NULL) {
- warnx(_("cannot open password database."));
+ warnx(_("cannot open password database"));
sleep(2);
return EXIT_FAILURE;
}
@@ -923,9 +954,6 @@ int main(int argc, char **argv)
tcinit(con);
}
ptr = (&consoles)->next;
- usemask = (uint32_t*) mmap(NULL, sizeof(uint32_t),
- PROT_READ|PROT_WRITE,
- MAP_ANONYMOUS|MAP_SHARED, -1, 0);
if (ptr->next == &consoles) {
con = list_entry(ptr, struct console, entry);
@@ -942,7 +970,6 @@ int main(int argc, char **argv)
switch ((con->pid = fork())) {
case 0:
mask_signal(SIGCHLD, SIG_DFL, NULL);
- /* fall through */
nofork:
setup(con);
while (1) {
@@ -971,9 +998,7 @@ int main(int argc, char **argv)
}
if (doshell) {
- *usemask |= (1<<con->id);
sushell(pwd);
- *usemask &= ~(1<<con->id);
failed++;
}
@@ -982,7 +1007,7 @@ int main(int argc, char **argv)
mask_signal(SIGINT, SIG_IGN, &saved_sigint);
if (failed) {
- fprintf(stderr, _("Can not execute su shell\n\n"));
+ fprintf(stderr, _("cannot execute su shell\n\n"));
break;
}
fprintf(stderr, _("Login incorrect\n\n"));
@@ -997,7 +1022,7 @@ int main(int argc, char **argv)
exit(0);
case -1:
warn(_("fork failed"));
- /* fall through */
+ /* fallthrough */
default:
break;
}
@@ -1006,28 +1031,80 @@ int main(int argc, char **argv)
} while (ptr != &consoles);
- while ((pid = wait(&status))) {
- if (errno == ECHILD)
+ do {
+ int ret;
+
+ status.si_pid = 0;
+ ret = waitid(P_ALL, 0, &status, WEXITED);
+
+ if (ret == 0)
break;
- if (pid < 0)
- continue;
- list_for_each(ptr, &consoles) {
- con = list_entry(ptr, struct console, entry);
- if (con->pid == pid) {
- *usemask &= ~(1<<con->id);
+ if (ret < 0) {
+ if (errno == ECHILD)
+ break;
+ if (errno == EINTR)
continue;
- }
- if (kill(con->pid, 0) < 0) {
- *usemask &= ~(1<<con->id);
+ }
+
+ errx(EXIT_FAILURE, _("cannot wait on su shell\n\n"));
+
+ } while (1);
+
+ list_for_each(ptr, &consoles) {
+ con = list_entry(ptr, struct console, entry);
+
+ if (con->fd < 0)
+ continue;
+ if (con->pid < 0)
+ continue;
+ if (con->pid == status.si_pid)
+ con->pid = -1;
+ else {
+ kill(con->pid, SIGTERM);
+ wait++;
+ }
+ }
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGCHLD);
+
+ do {
+ int signum, ret;
+
+ if (!wait)
+ break;
+
+ status.si_pid = 0;
+ ret = waitid(P_ALL, 0, &status, WEXITED|WNOHANG);
+
+ if (ret < 0) {
+ if (errno == ECHILD)
+ break;
+ if (errno == EINTR)
continue;
+ }
+
+ if (!ret && status.si_pid > 0) {
+ list_for_each(ptr, &consoles) {
+ con = list_entry(ptr, struct console, entry);
+
+ if (con->fd < 0)
+ continue;
+ if (con->pid < 0)
+ continue;
+ if (con->pid == status.si_pid) {
+ con->pid = -1;
+ wait--;
+ }
}
- if (*usemask & (1<<con->id))
- continue;
- kill(con->pid, SIGHUP);
- usleep(5000);
- kill(con->pid, SIGKILL);
+ continue;
}
- }
+
+ signum = sigtimedwait(&set, NULL, &sigwait);
+ if (signum != SIGCHLD && signum < 0 && errno == EAGAIN)
+ break;
+
+ } while (1);
mask_signal(SIGCHLD, SIG_DFL, NULL);
return EXIT_SUCCESS;
--
2.14.4

189
SPECS/util-linux.spec

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
Summary: A collection of basic system utilities
Name: util-linux
Version: 2.23.2
Release: 52%{?dist}
Release: 59%{?dist}
License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain
Group: System Environment/Base
URL: http://en.wikipedia.org/wiki/Util-linux
@ -30,7 +30,7 @@ BuildRequires: automake @@ -30,7 +30,7 @@ BuildRequires: automake
BuildRequires: libtool

### Sources
Source0: http://www.kernel.org/pub/linux/utils/util-linux/v2.23/util-linux-%{upstream_version}.tar.xz
Source0: ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.23/util-linux-%{upstream_version}.tar.xz
Source1: util-linux-login.pamd
Source2: util-linux-remote.pamd
Source3: util-linux-chsh-chfn.pamd
@ -77,6 +77,7 @@ Requires: audit-libs >= 1.0.6 @@ -77,6 +77,7 @@ Requires: audit-libs >= 1.0.6
Requires: libuuid = %{version}-%{release}
Requires: libblkid = %{version}-%{release}
Requires: libmount = %{version}-%{release}
Requires: libsmartcols = %{version}-%{release}

### Ready for upstream?
###
@ -147,7 +148,7 @@ Patch30: 2.25-wipefs-nested-pt.patch @@ -147,7 +148,7 @@ Patch30: 2.25-wipefs-nested-pt.patch
Patch31: 2.25-swapon-discard.patch
# 1080407 - libblkid XFS detection is too fragile
Patch32: 2.25-libblkid-xfs.patch
# RHEL6.6 port #1115442 - kill(1) doesn't check errno after calling strtol()
# RHEL6.6 port #1115442 - kill(1) doesn't check errno after calling strtol()
Patch33: 2.17-kill-strtol.patch
# 1127823 - losetup does not accept offset
Patch34: 2.24-losetup-offset.patch
@ -157,7 +158,7 @@ Patch35: 2.25-libblkid-gpt-512.patch @@ -157,7 +158,7 @@ Patch35: 2.25-libblkid-gpt-512.patch
Patch36: 2.24-libmount-3.14.patch
# backport from upstream: #1140591 - improve mount --move documentation
Patch37: 2.26-mount-man-move.patch
# RHEL6.6 port: #1131522 - backport --fork and --mount-proc to unshare(1)
# RHEL6.6 port: #1131522 - backport --fork and --mount-proc to unshare(1)
Patch38: 2.24-unshare-mount-fork.patch
# Backport from upstream (v2.25-214-g8a4c64e): #1113043 - backport lslogins(1)
Patch39: 2.26-libsmartcols.patch
@ -386,12 +387,82 @@ Patch148: 0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch @@ -386,12 +387,82 @@ Patch148: 0148-mkswap-tolerate-ENOTSUP-when-failing-to-relabel.patch
# 1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount
Patch149: 0149-libmount-fix-debug-message.patch

#
# RHEL7.6
#
# 1543428 - update lsns
Patch150: 0150-lsns-missing-ns-name-is-not-error.patch
Patch151: 0151-lsns-Fix-parser-for-proc-pid-stat-which-is-including.patch
# 1561350 - provide libsmartcols and libsmartcols-devel libraries
Patch152: 0152-libsmartcols-add-basic-tools-necessary-for-new-versi.patch
Patch153: 0153-libsmartcols-backport-upstream-version-v2.32-158-gc0.patch
Patch154: 0154-tests-backport-libsmartcols-tests.patch
# 1581611 - lslogins never shows lock passwords as PWD-LOCK
Patch155: 0155-lslogins-fix-password-verification.patch
# 1566674 - [RFE] Add warnings that have to be acknowledged to the -l flag in umount or remove the option
Patch156: 0156-umount-add-note-about-lazy.patch
# 1566390 - [RHEL-7.5] losetup can not detach all loop devices
Patch157: 0157-losetup-add-info-about-lazy-detach-to-manpage.patch
# 1562125 - "setarch ppc<*>" fails with "Unrecognized architecture"
Patch158: 0158-setarch-Fix-ppc64le-architectures.patch
# 1528567 - [RFE] Provide 'dig-holes' functionality for fallocate
Patch159: 0159-fallocate-backport-v2.32-164-g641af90dc.patch
# 1528959 - rbind creates duplicate entries in /proc/mounts
Patch160: 0160-libmount-fix-mnt_table_is_fs_mounted-for-rbind.patch
# 1538721 - mount man page says sync option has no effect for ext4
Patch161: 0161-mount-add-ext4-to-some-places-in-man-page.patch
# 1252764 - icrnl is not set when autologin is used
Patch162: 0162-agetty-keep-c_iflags-unmodified-on-autologin.patch
# 1561200 - [RFE] - sulogin: improve support for locked root account
Patch163: 0163-sulogin-don-t-use-strcpy-enlarge-pwd-line-buffer.patch
Patch164: 0164-sulogin-improve-support-for-locked-root-account.patch
Patch165: 0165-sulogin-Always-make-echo-work-after-performing-getpa.patch
Patch166: 0166-sulogin-make-getpasswd-.-return-NULL-on-D.patch
Patch167: 0167-sulogin-bail-out-from-getpasswd-.-on-timeout.patch
# 1566432 - [RHEL-7.5] losetup: /dev/loop1: failed to set up loop device
Patch168: 0168-losetup-keep-f-and-devname-mutually-exclusive.patch
# 1579439 - RHEL 7.5 - lscpu shows wrong sockets, threads on max config (32TB) POWER8 machine (util-linux)
Patch169: 0169-lscpu-fix-mzx-min-MHz-reporting.patch
Patch170: 0170-chcpu-cleanup-return-codes.patch
Patch171: 0171-chcpu-cleanup-stdout-stderr-usage.patch
Patch172: 0172-lscpu-chcpu-Avoid-use-of-the-old-CPU-macros.patch
Patch173: 0173-chcpu-Fix-maximal-number-of-CPUs.patch
# 1594681 - [RHEL7.2] blkid does not output swap area
Patch174: 0174-libblkid-minix-Match-minix-superblock-types.patch
Patch175: 0175-libblkid-minix-Sanity-check-superblock-s_state-for-v.patch
Patch176: 0176-libblkid-minix-Use-same-checks-for-version-3.patch
# 1618711 - exec option in mount unable to override the implicit noexec in user option
Patch177: 0177-mount-append-inverting-options-for-mount.-type-on-us.patch
# 1616264 - Login to emergency shell failed
Patch178: 0178-sulogin-backport-RHEL-8-version.patch

%description
The util-linux package contains a large variety of low-level system
utilities that are necessary for a Linux system to function. Among
others, Util-linux contains the fdisk configuration tool and the login
program.

%package -n libsmartcols
Summary: Formatting library for ls-like programs.
Group: Development/Libraries
License: LGPLv2+

%description -n libsmartcols
This is library for ls-like terminal programs, part of util-linux.


%package -n libsmartcols-devel
Summary: Formatting library for ls-like programs.
Group: Development/Libraries
License: LGPLv2+
Requires: libsmartcols = %{version}-%{release}
Requires: pkgconfig

%description -n libsmartcols-devel
This is development library and headers for ls-like terminal programs,
part of util-linux.


%package -n libmount
Summary: Device mounting library
Group: Development/Libraries
@ -631,7 +702,7 @@ for I in /sbin/sfdisk \ @@ -631,7 +702,7 @@ for I in /sbin/sfdisk \
%doc Documentation/sfdisk.txt \
/sbin/cfdisk \
%{_mandir}/man8/cfdisk.8*; do

rm -f $RPM_BUILD_ROOT$I
done
%endif
@ -644,7 +715,7 @@ rmdir ${RPM_BUILD_ROOT}%{_datadir}/getopt @@ -644,7 +715,7 @@ rmdir ${RPM_BUILD_ROOT}%{_datadir}/getopt
ln -sf ../proc/self/mounts %{buildroot}/etc/mtab

# remove static libs
rm -f $RPM_BUILD_ROOT%{_libdir}/lib{uuid,blkid,mount}.a
rm -f $RPM_BUILD_ROOT%{_libdir}/lib{uuid,blkid,mount,smartcols}.a

# find MO files
%find_lang %name
@ -703,6 +774,9 @@ done @@ -703,6 +774,9 @@ done
%post -n libmount -p /sbin/ldconfig
%postun -n libmount -p /sbin/ldconfig

%post -n libsmartcols -p /sbin/ldconfig
%postun -n libsmartcols -p /sbin/ldconfig

%pre -n uuidd
getent group uuidd >/dev/null || groupadd -r uuidd
getent passwd uuidd >/dev/null || \
@ -1066,6 +1140,18 @@ fi @@ -1066,6 +1140,18 @@ fi
%{compldir}/uuidd


%files -n libsmartcols
%defattr(-,root,root)
%doc libsmartcols/COPYING
%{_libdir}/libsmartcols.so.*

%files -n libsmartcols-devel
%defattr(-,root,root)
%{_libdir}/libsmartcols.so
%{_includedir}/libsmartcols
%{_libdir}/pkgconfig/smartcols.pc


%files -n libmount
%defattr(-,root,root)
%doc libmount/COPYING
@ -1118,6 +1204,39 @@ fi @@ -1118,6 +1204,39 @@ fi
%{_libdir}/pkgconfig/uuid.pc

%changelog
* Mon Aug 20 2018 Karel Zak <kzak@redhat.com> 2.23.2-59
- fix #1618711 - exec option in mount unable to override the implicit noexec in user option
- fix #1616264 - Login to emergency shell failed

* Wed Jul 04 2018 Karel Zak <kzak@redhat.com> 2.23.2-58
- fix #1594681 - [RHEL7.2] blkid does not output swap area

* Thu Jun 14 2018 Karel Zak <kzak@redhat.com> 2.23.2-57
- add another ppc aliases to setarch (#1562125)

* Wed Jun 13 2018 Karel Zak <kzak@redhat.com> 2.23.2-56
- backport another chcpu patches for #1579439

* Fri Jun 08 2018 Karel Zak <kzak@redhat.com> 2.23.2-55
- improve fallocate patch backward compatibility (#1528567)

* Thu Jun 07 2018 Karel Zak <kzak@redhat.com> 2.23.2-54
- fix #1581611 - lslogins never shows lock passwords as PWD-LOCK
- fix #1579439 - RHEL 7.5 - lscpu shows wrong sockets, threads on max config (32TB) POWER8 machine (util-linux)
- fix #1566674 - [RFE] Add warnings that have to be acknowledged to the -l flag in umount or remove the option
- fix #1566390 - [RHEL-7.5] losetup can not detach all loop devices
- fix #1562125 - "setarch ppc<*>" fails with "Unrecognized architecture"
- fix #1528567 - [RFE] Provide 'dig-holes' functionality for fallocate
- fix #1528959 - rbind creates duplicate entries in /proc/mounts
- fix #1538721 - mount man page says sync option has no effect for ext4
- fix #1252764 - icrnl is not set when autologin is used
- fix #1561200 - [RFE] - sulogin: improve support for locked root account
- fix #1566432 - [RHEL-7.5] losetup: /dev/loop1: failed to set up loop device

* Thu May 31 2018 Karel Zak <kzak@redhat.com> 2.23.2-53
- fix #1543428 - update lsns
- fix #1561350 - provide libsmartcols and libsmartcols-devel libraries

* Fri Feb 02 2018 Karel Zak <kzak@redhat.com> 2.23.2-52
- fix #1534893 - RHEL7: util-linux: mount/unmount ASLR bypass via environment variable in libmount

@ -1584,7 +1703,7 @@ fi @@ -1584,7 +1703,7 @@ fi
* Wed Jun 30 2010 Karel Zak <kzak@redhat.com> 2.18-1
- upgrade to the final 2.18
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-ReleaseNotes

* Fri Jun 18 2010 Karel Zak <kzak@redhat.com> 2.18-0.2
- upgrade to 2.18-rc2
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-rc2-ChangeLog
@ -1652,7 +1771,7 @@ fi @@ -1652,7 +1771,7 @@ fi

* Mon Oct 19 2009 Karel Zak <kzak@redhat.com> 2.17-0.1.git5e51568
- upgrade to pre-release snapshot (official changelog not available yet, see
http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git for now)
http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git for now)
- new commands: fallocate, unshare, wipefs
- libblkid supports topology and partitions probing
- remove support for --rmpart[s] from blockdev(8) (util-linux-ng-2.14-blockdev-rmpart.patch)
@ -1714,7 +1833,7 @@ fi @@ -1714,7 +1833,7 @@ fi
* Thu Jun 4 2009 Karel Zak <kzak@redhat.com> 2.15.1-0.1
- upgrade to 2.15.1-rc1
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.15/v2.15-ReleaseNotes
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.15/v2.15.1-rc1-ChangeLog
ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.15/v2.15.1-rc1-ChangeLog
- merged patches:
util-linux-ng-2.14-login-remote.patch
util-linux-ng-2.14-fdisk-4k-I.patch
@ -1730,7 +1849,7 @@ fi @@ -1730,7 +1849,7 @@ fi

* Thu Apr 2 2009 Karel Zak <kzak@redhat.com> 2.14.2-8
- fix #490769 - post scriptlet failed (thanks to Dan Horak)

* Fri Mar 20 2009 Karel Zak <kzak@redhat.com> 2.14.2-7
- fix some nits in mount.tmpfs

@ -1904,7 +2023,7 @@ fi @@ -1904,7 +2023,7 @@ fi
- fix #218915 - fdisk -b 4K
- upgrade to -pre7 release
- fix building problem with raw0 patch
- fix #217186 - /bin/sh: @MKINSTALLDIRS@: No such file or directory
- fix #217186 - /bin/sh: @MKINSTALLDIRS@: No such file or directory
(port po/Makefile.in.in from gettext-0.16)
- sync with FC6 and RHEL5:
- fix #216489 - SCHED_BATCH option missing in chrt
@ -1930,7 +2049,7 @@ fi @@ -1930,7 +2049,7 @@ fi

* Fri Sep 15 2006 Karel Zak <kzak@redhat.com> 2.13-0.41
- fix #205038 - mount not allowing sloppy option (exports "-s"
to external /sbin/mount.nfs(4) calls)
to external /sbin/mount.nfs(4) calls)
- fix minor bug in util-linux-2.13-mount-twiceloop.patch
- fix #188193- util-linux should provide plugin infrastructure for HAL

@ -1963,8 +2082,8 @@ fi @@ -1963,8 +2082,8 @@ fi

* Mon Jul 17 2006 Karel Zak <kzak@redhat.com> 2.13-0.32
- add IPv6 support to the login command (patch by Milan Zazrivec)
- fix #198626 - add keyinit instructions to the login PAM script
(patch by David Howells)
- fix #198626 - add keyinit instructions to the login PAM script
(patch by David Howells)

* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - 2.13-0.31.1
- rebuild
@ -1975,7 +2094,7 @@ fi @@ -1975,7 +2094,7 @@ fi
* Mon Jul 10 2006 Karsten Hopp <karsten@redhat.de> 2.13-0.30
- silence install in minimal buildroot without /var/log

* Fri Jul 7 2006 Karel Zak <kzak@redhat.com> 2.13-0.29
* Fri Jul 7 2006 Karel Zak <kzak@redhat.com> 2.13-0.29
- include the raw command for RHELs

* Mon Jun 26 2006 Florian La Roche <laroche@redhat.com> 2.13-0.28
@ -1997,7 +2116,7 @@ fi @@ -1997,7 +2116,7 @@ fi
- fix #191230 - using mount --move results in wrong data in /etc/mtab
- added mount subtrees support
- fdisk: wrong number of sectors for large disks (suse#160822)
- merge fdisk-xvd (#182553) with new fdisk-isfull (#188981) patch
- merge fdisk-xvd (#182553) with new fdisk-isfull (#188981) patch
- fix #181549 - raw(8) manpage has old information about dd
- remove asm/page.h usage

@ -2050,7 +2169,7 @@ fi @@ -2050,7 +2169,7 @@ fi
* Thu Jan 19 2006 Steve Dickson <steved@redhat.com> 2.13-0.14
- Updated the gssd_check() and idmapd_check(), used with
nfsv4 mounts, to looked for the correct file in /var/lock/subsys
which stops bogus warnings.
which stops bogus warnings.

* Tue Jan 3 2006 Karel Zak <kzak@redhat.com> 2.13-0.13
- fix #174676 - hwclock audit return code mismatch
@ -2166,7 +2285,7 @@ fi @@ -2166,7 +2285,7 @@ fi

* Fri Feb 25 2005 Steve Dickson <SteveD@RedHat.com> 2.12p-2
- Changed nfsmount to only use reserve ports when necessary
(bz# 141773)
(bz# 141773)

* Thu Dec 23 2004 Elliot Lee <sopwith@redhat.com> 2.12p-1
- Update to util-linux-2.12p. This changes swap header format
@ -2178,7 +2297,7 @@ fi @@ -2178,7 +2297,7 @@ fi

* Tue Dec 7 2004 Steve Dickson <SteveD@RedHat.com> 2.12a-20
- Corrected a buffer overflow problem with nfs mounts.
(bz# 141733)
(bz# 141733)

* Wed Dec 01 2004 Elliot Lee <sopwith@redhat.com> 2.12a-19
- Patches for various bugs.
@ -2274,8 +2393,8 @@ fi @@ -2274,8 +2393,8 @@ fi
- mkcramfs: use PAGE_SIZE for default blocksize (#118681)

* Sat Mar 20 2004 <SteveD@RedHat.com>
- Updated the nfs-mount.patch to correctly
handle the mounthost option and to ignore
- Updated the nfs-mount.patch to correctly
handle the mounthost option and to ignore
servers that do not set auth flavors

* Tue Mar 16 2004 Dan Walsh <dwalsh@RedHat.com> 2.12-13
@ -2286,7 +2405,7 @@ fi @@ -2286,7 +2405,7 @@ fi
- Added two checks to the nfs4 path what will print warnings
when rpc.idmapd and rpc.gssd are not running
- Ping NFS v4 servers before diving into kernel
- Make v4 mount interruptible which also make the intr option on by default
- Make v4 mount interruptible which also make the intr option on by default

* Sun Mar 13 2004 <SteveD@RedHat.com>
- Reworked how the rpc.idmapd and rpc.gssd checks were
@ -2307,10 +2426,10 @@ fi @@ -2307,10 +2426,10 @@ fi
- Tried to make nfs error message a bit more meaninful
- Cleaned up some warnings

* Sun Mar 7 2004 Steve Dickson <SteveD@RedHat.com>
* Sun Mar 7 2004 Steve Dickson <SteveD@RedHat.com>
- Added pesudo flavors for nfsv4 mounts.
- Added BuildRequires: libselinux-devel and Requires: libselinux
when WITH_SELINUX is set.
when WITH_SELINUX is set.

* Fri Feb 27 2004 Dan Walsh <dwalsh@redhat.com> 2.12-5
- check for 2.6.3 kernel in mount options
@ -2339,7 +2458,7 @@ fi @@ -2339,7 +2458,7 @@ fi
* Thu Jan 15 2004 Elliot Lee <sopwith@redhat.com> 2.12pre-1
- 2.12pre-1
- Merge mount/losetup packages into the main package (#112324)
- Lose separate
- Lose separate

* Mon Nov 3 2003 Dan Walsh <dwalsh@redhat.com> 2.11y-35.sel
- remove selinux code from login and use pam_selinux
@ -2477,7 +2596,7 @@ ipcs fixes @@ -2477,7 +2596,7 @@ ipcs fixes
- Include isosize util

* Wed Aug 7 2002 Elliot Lee <sopwith@redhat.com> 2.11r-9
- Patch120 (skipraid2) to fix #70353, because the original patch was
- Patch120 (skipraid2) to fix #70353, because the original patch was
totally useless.

* Fri Aug 2 2002 Elliot Lee <sopwith@redhat.com> 2.11r-8
@ -2497,7 +2616,7 @@ totally useless. @@ -2497,7 +2616,7 @@ totally useless.
- only require usermode if we're shipping kbdrate here

* Fri Jun 28 2002 Trond Eivind Glomsrod <teg@redhat.com> 2.11r-3
- Port the large swap patch to new util-linux... the off_t changes
- Port the large swap patch to new util-linux... the off_t changes
now in main aren't sufficient

* Thu Jun 27 2002 Elliot Lee <sopwith@redhat.com> 2.11r-2
@ -2508,17 +2627,17 @@ totally useless. @@ -2508,17 +2627,17 @@ totally useless.
- Remove unused patches

* Thu Jun 27 2002 Elliot Lee <sopwith@redhat.com> 2.11n-19
- Make a note here that this package was the source of the single change
contained in util-linux-2.11f-18 (in 7.2/Alpha), and also contains the
- Make a note here that this package was the source of the single change
contained in util-linux-2.11f-18 (in 7.2/Alpha), and also contains the
rawman patch from util-linux-2.11f-17.1 (in 2.1AS).
- Package has no runtime deps on slang, so remove the BuildRequires:
- Package has no runtime deps on slang, so remove the BuildRequires:
slang-devel.

* Fri Jun 21 2002 Tim Powers <timp@redhat.com>
- automated rebuild

* Thu Jun 20 2002 Elliot Lee <sopwith@redhat.com> 2.11n-17
- Fix teg's swapondetect patch to not print out the usage message when
- Fix teg's swapondetect patch to not print out the usage message when
'swapon -a -e' is run. (#66690) (edit existing patch)
- Apply hjl's utmp handling patch (#66950) (patch116)
- Fix fdisk man page notes on IDE disk partition limit (#64013) (patch117)
@ -2601,7 +2720,7 @@ slang-devel. @@ -2601,7 +2720,7 @@ slang-devel.
- Don't make the pivot_root.8 man page executable(!)

* Tue Oct 23 2001 Elliot Lee <sopwith@redhat.com> 2.11f-13
- Patch/idea #76 from HJL, fixes bug #54741 (race condition in login
- Patch/idea #76 from HJL, fixes bug #54741 (race condition in login
acquisition of controlling terminal).

* Thu Oct 11 2001 Bill Nottingham <notting@redhat.com>
@ -2974,7 +3093,7 @@ acquisition of controlling terminal). @@ -2974,7 +3093,7 @@ acquisition of controlling terminal).
* Mon Mar 22 1999 Erik Troan <ewt@redhat.com>
- added vigr to file list

* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com>
* Sun Mar 21 1999 Cristian Gafton <gafton@redhat.com>
- auto rebuild in the new build environment (release 12)

* Thu Mar 18 1999 Cristian Gafton <gafton@redhat.com>
@ -3057,7 +3176,7 @@ acquisition of controlling terminal). @@ -3057,7 +3176,7 @@ acquisition of controlling terminal).
- use proper tc*() calls rather then ioctl's

* Sun Dec 21 1997 Cristian Gafton <gafton@redhat.com>
- fixed a security problem in chfn and chsh accepting too
- fixed a security problem in chfn and chsh accepting too
long gecos fields

* Fri Dec 19 1997 Mike Wangsmo <wanger@redhat.com>
@ -3073,7 +3192,7 @@ acquisition of controlling terminal). @@ -3073,7 +3192,7 @@ acquisition of controlling terminal).
- added vfat32 filesystem type to list recognized by fdisk

* Fri Oct 10 1997 Erik Troan <ewt@redhat.com>
- don't build clock on the alpha
- don't build clock on the alpha
- don't install chkdupexe

* Thu Oct 02 1997 Michael K. Johnson <johnsonm@redhat.com>

Loading…
Cancel
Save