basebuilder_pel7x64builder0
6 years ago
30 changed files with 11513 additions and 35 deletions
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
@ -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 |
||||||
|
|
Loading…
Reference in new issue