Hello community, here is the log from the commit of package procps for openSUSE:Factory checked in at 2018-02-03 15:35:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/procps (Old) and /work/SRC/openSUSE:Factory/.procps.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "procps" Sat Feb 3 15:35:50 2018 rev:108 rq:570891 version:3.3.12 Changes: -------- --- /work/SRC/openSUSE:Factory/procps/procps.changes 2018-01-07 17:20:47.174926171 +0100 +++ /work/SRC/openSUSE:Factory/.procps.new/procps.changes 2018-02-03 15:35:52.343951997 +0100 @@ -1,0 +2,12 @@ +Tue Jan 30 09:39:14 UTC 2018 - wer...@suse.de + +- Remove patch procps-ng-3.3.12-sysctl-iobuf-write.patch (bsc#1077746) +- Add patches + 0001-Preload-sysctl-lines-even-if-longer-than-stdio-buffe.patch + 0002-Add-flexible-buffered-I-O-based-on-fopencookie-3.patch + 0003-Use-new-standard-I-O-for-reading-writing-sysctl-valu.patch + from my project https://gitlab.com/bitstreamout/procps/tree/procio + which implements a flexible buffer for reading and writing values + below /proc/sys (bsc#1039941) + +------------------------------------------------------------------- Old: ---- procps-ng-3.3.12-sysctl-iobuf-write.patch New: ---- 0001-Preload-sysctl-lines-even-if-longer-than-stdio-buffe.patch 0002-Add-flexible-buffered-I-O-based-on-fopencookie-3.patch 0003-Use-new-standard-I-O-for-reading-writing-sysctl-valu.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ procps.spec ++++++ --- /var/tmp/diff_new_pack.qTaRUK/_old 2018-02-03 15:35:53.419901739 +0100 +++ /var/tmp/diff_new_pack.qTaRUK/_new 2018-02-03 15:35:53.423901552 +0100 @@ -1,7 +1,7 @@ # # spec file for package procps # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -66,7 +66,11 @@ # PATCH-FIX-SUSE -- Ignore EIO on reading unset value of e.g. /proc/sys/net/ipv6/conf/all/stable_secret Patch36: procps-ng-3.3.12-stable_secret.patch # PATCH-ENHANCE-SUSE -- Use increased buffer on writing /proc/sys/net/ipv4/ip_local_reserved_ports -Patch37: procps-ng-3.3.12-sysctl-iobuf-write.patch +#Patch37: procps-ng-3.3.12-sysctl-iobuf-write.patch +Patch37: 0001-Preload-sysctl-lines-even-if-longer-than-stdio-buffe.patch +Patch38: 0002-Add-flexible-buffered-I-O-based-on-fopencookie-3.patch +Patch39: 0003-Use-new-standard-I-O-for-reading-writing-sysctl-valu.patch + BuildRequires: automake BuildRequires: dejagnu BuildRequires: libselinux-devel @@ -155,7 +159,9 @@ %patch34 %patch35 %patch36 -%patch37 +%patch37 -b .0001 +%patch38 -b .0002 +%patch39 -b .0003 %build # @@ -395,6 +401,7 @@ %{_includedir}/proc/alloc.h %{_includedir}/proc/devname.h %{_includedir}/proc/escape.h +%{_includedir}/proc/procio.h %{_includedir}/proc/procps.h %{_includedir}/proc/pwcache.h %{_includedir}/proc/readproc.h @@ -406,6 +413,7 @@ %{_includedir}/proc/whattime.h %{_libdir}/libprocps.so %{_libdir}/pkgconfig/libprocps.pc +%{_mandir}/man3/procio.3%{ext_man} %{_mandir}/man3/openproc.3%{ext_man} %{_mandir}/man3/readproc.3%{ext_man} %{_mandir}/man3/readproctab.3%{ext_man} ++++++ 0001-Preload-sysctl-lines-even-if-longer-than-stdio-buffe.patch ++++++ >From 702a464040bef969db7483d3cc122dfeec653d6f Mon Sep 17 00:00:00 2001 From: Werner Fink <wer...@suse.de> Date: Thu, 18 Jan 2018 11:06:55 +0100 Subject: [PATCH 1/3] Preload sysctl lines even if longer than stdio buffer by using getline(3) to use a dynamically increased buffer if required by the input found in sysctl configuration files. Signed-off-by: Werner Fink <wer...@suse.de> --- sysctl.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git sysctl.c sysctl.c index 7c05243..42162f5 100644 --- sysctl.c +++ sysctl.c @@ -511,18 +511,21 @@ static int pattern_match(const char *string, const char *pat) */ static int Preload(const char *restrict const filename) { - char oneline[LINELEN]; - char buffer[LINELEN]; + char *oneline; FILE *fp; char *t; int n = 0; int rc = 0; + size_t blen = LINELEN; + ssize_t rlen; char *name, *value; glob_t globbuf; int globerr; int globflg; int j; + oneline = xmalloc(blen); + globflg = GLOB_NOCHECK; #ifdef GLOB_BRACE globflg |= GLOB_BRACE; @@ -544,13 +547,19 @@ static int Preload(const char *restrict const filename) ? stdin : fopen(globbuf.gl_pathv[j], "r"); if (!fp) { xwarn(_("cannot open \"%s\""), globbuf.gl_pathv[j]); - return -1; + rc = -1; + goto out; } - while (fgets(oneline, sizeof oneline, fp)) { + while ((rlen = getline(&oneline, &blen, fp)) != -1) { + size_t offset; + n++; - t = StripLeadingAndTrailingSpaces(oneline); + if (rlen < 2) + continue; + + t = StripLeadingAndTrailingSpaces(oneline); if (strlen(t) < 2) continue; @@ -569,6 +578,10 @@ static int Preload(const char *restrict const filename) if (pattern && !pattern_match(name, pattern)) continue; + offset = strlen(name); + memmove(&oneline[0], name, offset); + oneline[offset++] = '='; + value = strtok(NULL, "\n\r"); if (!value || !*value) { xwarnx(_("%s(%d): invalid syntax, continuing..."), @@ -580,12 +593,16 @@ static int Preload(const char *restrict const filename) value++; /* should NameOnly affect this? */ - sprintf(buffer, "%s=%s", name, value); - rc |= WriteSetting(buffer); + memmove(&oneline[offset], value, strlen(value)); + offset += strlen(value); + oneline[offset] = '\0'; + + rc |= WriteSetting(oneline); } fclose(fp); } +out: return rc; } -- 2.16.1 ++++++ 0002-Add-flexible-buffered-I-O-based-on-fopencookie-3.patch ++++++ >From c69b0f34444cfc15489b0d6b076a10f4d4478cb7 Mon Sep 17 00:00:00 2001 From: Werner Fink <wer...@suse.de> Date: Thu, 18 Jan 2018 11:26:37 +0100 Subject: [PATCH 2/3] Add flexible buffered I/O based on fopencookie(3) to be able to read and write large buffers below /proc. The buffers and file offsets are handled dynamically on the required buffer size at read, that is lseek(2) is used to determine this size. Large buffers at write are split at a delimeter into pieces and also lseek(2) is used to write each of them. Signed-off-by: Werner Fink <wer...@suse.de> --- Makefile.am | 4 proc/libprocps.sym | 1 proc/procio.3 | 80 ++++++++++++++ proc/procio.c | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++++ proc/procio.h | 11 + 5 files changed, 389 insertions(+) --- Makefile.am +++ Makefile.am 2018-01-30 09:22:55.979438743 +0000 @@ -167,6 +167,8 @@ proc_libprocps_la_SOURCES = \ proc/devname.h \ proc/escape.c \ proc/escape.h \ + proc/procio.c \ + proc/procio.h \ proc/procps-private.h \ proc/procps.h \ proc/pwcache.c \ @@ -191,6 +193,7 @@ proc_libprocps_la_include_HEADERS = \ proc/alloc.h \ proc/devname.h \ proc/escape.h \ + proc/procio.h \ proc/procps.h \ proc/pwcache.h \ proc/readproc.h \ @@ -202,6 +205,7 @@ proc_libprocps_la_include_HEADERS = \ proc/whattime.h dist_man_MANS += \ + proc/procio.3 \ proc/openproc.3 \ proc/readproc.3 \ proc/readproctab.3 --- proc/libprocps.sym +++ proc/libprocps.sym 2018-01-30 09:21:46.596751319 +0000 @@ -8,6 +8,7 @@ global: escape_str; escape_strlist; escaped_copy; + fprocopen; free_slabinfo; freeproc; get_ns_id; --- proc/procio.3 +++ proc/procio.3 2018-01-30 09:21:46.596751319 +0000 @@ -0,0 +1,80 @@ +'\" t -*- coding: UTF-8 -*- +.\" +.\" This file describes the readproc interface to the /proc filesystem +.\" +.\" Copyright 2018 Werner Fink <wer...@suse.de> +.\" +.\" Permission is granted to make and distribute verbatim copies of this +.\" manual provided the copyright notice and this permission notice are +.\" preserved on all copies. +.\" +.\" Permission is granted to copy and distribute modified versions of this +.\" manual under the conditions for verbatim copying, provided that the +.\" entire resulting derived work is distributed under the terms of a +.\" permission notice identical to this one +.\" +.\" Formatted or processed versions of this manual, if unaccompanied by +.\" the source, must acknowledge the copyright and authors of this work. +.\" +.TH PROCIO 3 "16 January 2018" "Linux Manpage" "Linux Programmer's Manual" +.SH NAME +fprocopen \- stream open functions on files below /proc/## +.SH SYNOPSIS +.B #define _GNU_SOURCE +.br +.B #include <stdio.h> +.br +.B #include <proc/procio.h> +.sp +.BI "FILE *fprocopen(const char *path, const char *mode); + +.SH DESCRIPTION + +The +.B fprocopen +function opens files below +.I /proc/## +whose name is the string to by path and associates a stream with it. +The argument +.I mode +points to a string beginning with one of the following sequences +.TP +.B r +Open a file below +.I /proc/## +for reading even large buffers. The stream is positioned at +the beginning of the file. +.TP +.BR w [ <del> ] +Open a file below +.I /proc/## +for writing even large buffers. The optional delimeter character +can be one of the follwoing +.BR '\ ' ,\ ',' ,\ '.' ,\ and\ ':' +where the default is the colon +.BR ',' . +This allows to split very large input lines into pieces at this +delimeter and write each of them to the opened file below +.IR /proc/## . +.TP +.B e +The underlying file descriptor will be closed if you use any +of the ‘exec...’ functions within your code. +.PP +The internal API allows to use stdio functions to read and write +large buffers below +.IR /proc/## . +.PP +.SH SEE ALSO +.BR fopen (3), +.br +.BR fopencookie (3) +.br +.BR setvbuf (3) +.br +.BR lseek (3) +.PP +.SH COPYRIGHT +2018 Werner Fink, +.SH AUTHOR +Werner Fink <wer...@suse.de> --- proc/procio.c +++ proc/procio.c 2018-01-30 09:21:46.596751319 +0000 @@ -0,0 +1,293 @@ +/* + * procio.c -- Replace stdio for read and write on files below + * proc to be able to read and write large buffers as well. + * + * Copyright (C) 2017 Werner Fink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include <errno.h> +#include <fcntl.h> +#include <libio.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +typedef struct pcookie { + char *buf; + size_t count; + size_t length; + off_t offset; + int fd; + int delim; + int final:1; +} pcookie_t; + +static ssize_t proc_read(void *, char *, size_t); +static ssize_t proc_write(void *, const char *, size_t); +static int proc_close(void *); + +__extension__ +static cookie_io_functions_t procio = { + .read = proc_read, + .write = proc_write, + .seek = NULL, + .close = proc_close, +}; + +FILE *fprocopen(const char *path, const char *mode) +{ + pcookie_t *cookie = NULL; + FILE *handle = NULL; + mode_t flags = 0; + size_t len = 0; + int c, delim; + + if (!mode || !(len = strlen(mode))) { + errno = EINVAL; + goto out; + } + + /* No append mode possible */ + switch (mode[0]) { + case 'r': + flags |= O_RDONLY; + break; + case 'w': + flags |= O_WRONLY|O_TRUNC; + break; + default: + errno = EINVAL; + goto out; + } + + delim = ','; /* default delimeter is the colon */ + for (c = 1; c < len; c++) { + switch (mode[c]) { + case '\0': + break; + case '+': + errno = EINVAL; + goto out; + case 'e': + flags |= O_CLOEXEC; + continue; + case 'b': + case 'm': + case 'x': + /* ignore this */ + continue; + default: + if (mode[c] == ' ' || (mode[c] >= ',' && mode[c] <= '.') || mode[c] == ':') + delim = mode[c]; + else { + errno = EINVAL; + goto out; + } + break; + } + break; + } + + cookie = (pcookie_t *)malloc(sizeof(pcookie_t)); + if (!cookie) + goto out; + cookie->count = BUFSIZ; + cookie->buf = (char *)malloc(cookie->count); + if (!cookie->buf) { + int errsv = errno; + free(cookie); + errno = errsv; + goto out; + } + cookie->final = 0; + cookie->offset = 0; + cookie->length = 0; + cookie->delim = delim; + + cookie->fd = openat(AT_FDCWD, path, flags); + if (cookie->fd < 0) { + int errsv = errno; + free(cookie->buf); + free(cookie); + errno = errsv; + goto out; + } + + handle = fopencookie(cookie, mode, procio); + if (!handle) { + int errsv = errno; + close(cookie->fd); + free(cookie->buf); + free(cookie); + errno = errsv; + goto out; + } +out: + return handle; +} + +static +ssize_t proc_read(void *c, char *buf, size_t count) +{ + pcookie_t *cookie = c; + ssize_t len = -1; + void *ptr; + + if (cookie->count < count) { + ptr = realloc(cookie->buf, count); + if (!ptr) + goto out; + cookie->buf = ptr; + cookie->count = count; + } + + while (!cookie->final) { + len = read(cookie->fd, cookie->buf, cookie->count); + + if (len <= 0) { + if (len == 0) { + /* EOF */ + cookie->final = 1; + cookie->buf[cookie->length] = '\0'; + break; + } + goto out; /* error or done */ + } + + cookie->length = len; + + if (cookie->length < cookie->count) + continue; + + /* Likly to small buffer here */ + + lseek(cookie->fd, 0, SEEK_SET); /* reset for a retry */ + + ptr = realloc(cookie->buf, cookie->count += BUFSIZ); + if (!ptr) + goto out; + cookie->buf = ptr; + } + + len = count; + if (cookie->length - cookie->offset < len) + len = cookie->length - cookie->offset; + + if (len < 0) + len = 0; + + if (len) { + (void)memcpy(buf, cookie->buf+cookie->offset, len); + cookie->offset += len; + } else + len = EOF; +out: + return len; +} + +#define LINELEN 4096 + +static +ssize_t proc_write(void *c, const char *buf, size_t count) +{ + pcookie_t *cookie = c; + ssize_t len = -1; + void *ptr; + + if (!count) { + len = 0; + goto out; + } + + /* NL is the final input */ + cookie->final = memrchr(buf, '\n', count) ? 1 : 0; + + while (cookie->count < cookie->offset + count) { + ptr = realloc(cookie->buf, cookie->count += count); + if (!ptr) + goto out; + cookie->buf = ptr; + } + + len = count; + (void)memcpy(cookie->buf+cookie->offset, buf, count); + cookie->offset += count; + + if (cookie->final) { + len = write(cookie->fd, cookie->buf, cookie->offset); + if (len < 0 && errno == EINVAL) { + size_t offset; + off_t amount; + char *token; + /* + * Oops buffer might be to large, split buffer into + * pieces at delimeter if provided + */ + if (!cookie->delim) + goto out; /* Hey dude?! */ + offset = 0; + do { + token = NULL; + if (cookie->offset > LINELEN) + token = (char*)memrchr(cookie->buf+offset, ',', LINELEN); + else + token = (char*)memrchr(cookie->buf+offset, '\n', LINELEN); + if (token) + *token = '\n'; + else { + errno = EINVAL; + len = -1; + goto out; /* Wrong/Missing delimeter? */ + } + if (offset > 0) + lseek(cookie->fd, 1, SEEK_CUR); + + amount = token-(cookie->buf+offset)+1; + ptr = cookie->buf+offset; + + len = write(cookie->fd, ptr, amount); + if (len < 1 || len >= cookie->offset) + break; + + offset += len; + cookie->offset -= len; + + } while (cookie->offset > 0); + } + if (len > 0) + len = count; + } +out: + return len; +} + +static +int proc_close(void *c) +{ + pcookie_t *cookie = c; + close(cookie->fd); + free(cookie->buf); + free(cookie); + return 0; +} --- proc/procio.h +++ proc/procio.h 2018-01-30 09:21:46.596751319 +0000 @@ -0,0 +1,11 @@ +#ifndef PROCPS_PROC_PROCIO_H +#define PROCPS_PROC_PROCIO_H + +#include "procps.h" + +EXTERN_C_BEGIN + +extern FILE *fprocopen(const char *, const char *); + +EXTERN_C_END +#endif ++++++ 0003-Use-new-standard-I-O-for-reading-writing-sysctl-valu.patch ++++++ >From 97079405b6c7c7c39234d69c548d2f2fea4aa77e Mon Sep 17 00:00:00 2001 From: Werner Fink <wer...@suse.de> Date: Thu, 18 Jan 2018 11:38:02 +0100 Subject: [PATCH 3/3] Use new standard I/O for reading/writing sysctl values thereby use one allocated buffer for I/O which now might be increased by the stdio function getline(3) on the file if required. Signed-off-by: Werner Fink <wer...@suse.de> --- sysctl.c | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) --- sysctl.c +++ sysctl.c 2018-01-30 09:34:51.429936410 +0000 @@ -46,6 +46,7 @@ #include "fileutils.h" #include "nls.h" #include "xalloc.h" +#include "proc/procio.h" #include "proc/procps.h" #include "proc/version.h" @@ -68,6 +69,10 @@ static bool IgnoreError; static bool Quiet; static char *pattern; +#define LINELEN 4096 +static char *iobuf; +static size_t iolen = LINELEN; + /* Function prototypes. */ static int pattern_match(const char *string, const char *pat); static int DisplayAll(const char *restrict const path); @@ -160,14 +165,12 @@ static char *StripLeadingAndTrailingSpac /* * Read a sysctl setting */ -#define IOBUFSIZ (128<<10) -static char *iobuf; static int ReadSetting(const char *restrict const name) { int rc = 0; char *restrict tmpname; char *restrict outname; - char inbuf[1025]; + ssize_t rlen; FILE *restrict fp; struct stat ts; @@ -222,7 +225,7 @@ static int ReadSetting(const char *restr goto out; } - fp = fopen(tmpname, "r"); + fp = fprocopen(tmpname, "r"); if (!fp) { switch (errno) { @@ -245,10 +248,8 @@ static int ReadSetting(const char *restr break; } } else { - if (iobuf) - setvbuf(fp, iobuf, _IOFBF, IOBUFSIZ); errno = 0; - if (fgets(inbuf, sizeof inbuf - 1, fp)) { + if ((rlen = getline(&iobuf, &iolen, fp)) > 0) { /* this loop is required, see * /sbin/sysctl -a | egrep -6 dev.cdrom.info */ @@ -257,23 +258,23 @@ static int ReadSetting(const char *restr if (PrintName) { fprintf(stdout, "%s = ", outname); do { - fprintf(stdout, "%s", inbuf); - nlptr = &inbuf[strlen(inbuf) - 1]; + fprintf(stdout, "%s", iobuf); + nlptr = &iobuf[strlen(iobuf) - 1]; /* already has the \n in it */ if (*nlptr == '\n') break; - } while (fgets(inbuf, sizeof inbuf - 1, fp)); + } while ((rlen = getline(&iobuf, &iolen, fp)) > 0); if (*nlptr != '\n') putchar('\n'); } else { if (!PrintNewline) { - nlptr = strchr(inbuf, '\n'); + nlptr = strchr(iobuf, '\n'); if (nlptr) *nlptr = '\0'; } - fprintf(stdout, "%s", inbuf); + fprintf(stdout, "%s", iobuf); } - } while (fgets(inbuf, sizeof inbuf - 1, fp)); + } while ((rlen = getline(&iobuf, &iolen, fp)) > 0); } else { switch (errno) { case EACCES: @@ -440,7 +441,7 @@ static int WriteSetting(const char *sett goto out; } - fp = fopen(tmpname, "w"); + fp = fprocopen(tmpname, "w"); if (!fp) { switch (errno) { @@ -460,8 +461,6 @@ static int WriteSetting(const char *sett break; } } else { - if (iobuf) - setvbuf(fp, iobuf, _IOFBF, IOBUFSIZ); rc = fprintf(fp, "%s\n", value); if (0 < rc) rc = 0; @@ -503,20 +502,16 @@ static int pattern_match(const char *str return (1); } -#define LINELEN 4096 - /* * Preload the sysctl's from the conf file. We parse the file and then * reform it (strip out whitespace). */ static int Preload(const char *restrict const filename) { - char *oneline; FILE *fp; char *t; int n = 0; int rc = 0; - size_t blen = LINELEN; ssize_t rlen; char *name, *value; glob_t globbuf; @@ -524,8 +519,6 @@ static int Preload(const char *restrict int globflg; int j; - oneline = xmalloc(blen); - globflg = GLOB_NOCHECK; #ifdef GLOB_BRACE globflg |= GLOB_BRACE; @@ -551,7 +544,7 @@ static int Preload(const char *restrict goto out; } - while ((rlen = getline(&oneline, &blen, fp)) != -1) { + while ((rlen = getline(&iobuf, &iolen, fp)) > 0) { size_t offset; n++; @@ -559,7 +552,7 @@ static int Preload(const char *restrict if (rlen < 2) continue; - t = StripLeadingAndTrailingSpaces(oneline); + t = StripLeadingAndTrailingSpaces(iobuf); if (strlen(t) < 2) continue; @@ -579,8 +572,8 @@ static int Preload(const char *restrict continue; offset = strlen(name); - memmove(&oneline[0], name, offset); - oneline[offset++] = '='; + memmove(&iobuf[0], name, offset); + iobuf[offset++] = '='; value = strtok(NULL, "\n\r"); if (!value || !*value) { @@ -593,11 +586,11 @@ static int Preload(const char *restrict value++; /* should NameOnly affect this? */ - memmove(&oneline[offset], value, strlen(value)); + memmove(&iobuf[offset], value, strlen(value)); offset += strlen(value); - oneline[offset] = '\0'; + iobuf[offset] = '\0'; - rc |= WriteSetting(oneline); + rc |= WriteSetting(iobuf); } fclose(fp); @@ -835,7 +828,7 @@ int main(int argc, char *argv[]) argc -= optind; argv += optind; - iobuf = (char*)malloc(IOBUFSIZ); /* Allow to fail */ + iobuf = xmalloc(iolen); if (DisplayAllOpt) return DisplayAll(PROC_PATH);