From 56d9d5e7e701e71646679b2b8cefa9239ee59592 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Fri, 19 Jun 2015 21:00:46 +1000 Subject: [PATCH] library: Change linux version Added function procps_linux_version() which used to be an exported integer instead. Also changed the method of obtaining the linux version (more correctly the os release) to use a specific procfs entry. This works for both Linux and FreeBSD. --- proc/libprocps.sym | 2 +- proc/procps-private.h | 25 ++++++++++++++ proc/procps.h | 15 -------- proc/sysinfo.c | 3 +- proc/version.c | 80 ++++++++++++++++++------------------------- proc/version.h | 46 ++++++++++++++++--------- ps/global.c | 1 + top/top.c | 2 ++ 8 files changed, 93 insertions(+), 81 deletions(-) create mode 100644 proc/procps-private.h diff --git a/proc/libprocps.sym b/proc/libprocps.sym index b08d5714..ba2dbf7b 100644 --- a/proc/libprocps.sym +++ b/proc/libprocps.sym @@ -35,7 +35,6 @@ global: kb_swap_free; kb_swap_total; kb_swap_used; - linux_version_code; loadavg; look_up_our_self; lookup_wchan; @@ -60,6 +59,7 @@ global: unix_print_signals; uptime; user_from_uid; + procps_linux_version; local: *; }; diff --git a/proc/procps-private.h b/proc/procps-private.h new file mode 100644 index 00000000..ea9479b9 --- /dev/null +++ b/proc/procps-private.h @@ -0,0 +1,25 @@ +/* + * libprocps - Library to read proc filesystem + * + * 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 PROCPS_PRIVATE_H +#define PROCPS_PRIVATE_H + +#include + +#define PROCPS_EXPORT __attribute__ ((visibility("default"))) + +#endif diff --git a/proc/procps.h b/proc/procps.h index e39df798..c34dc056 100644 --- a/proc/procps.h +++ b/proc/procps.h @@ -78,21 +78,6 @@ #define OBSOLETE #endif -#if ( __GNUC__ == 3 && __GNUC_MINOR__ > 1 ) || __GNUC__ > 3 -// Tells gcc that function is library-internal; -// so no need to do dynamic linking at run-time. -// This might work with slightly older compilers too. -#define HIDDEN __attribute__((visibility("hidden"))) -// The opposite, in case -fvisibility=hidden used -#define EXPORT __attribute__((visibility("default"))) -// Tell g++ that a function won't throw exceptions. -#define NOTHROW __attribute__((__nothrow__)) -#else -#define HIDDEN -#define EXPORT -#define NOTHROW -#endif - // Like HIDDEN, but for an alias that gets created. // In gcc-3.2 there is an alias+hidden conflict. // Many will have patched this bug, but oh well. diff --git a/proc/sysinfo.c b/proc/sysinfo.c index e6450eff..b0af54f0 100644 --- a/proc/sysinfo.c +++ b/proc/sysinfo.c @@ -275,7 +275,7 @@ static int check_for_privs(void){ static void init_libproc(void) __attribute__((constructor)); static void init_libproc(void){ have_privs = check_for_privs(); - init_Linux_version(); /* Must be called before we check code */ + int linux_version_code = procps_linux_version(); cpuinfo(); page_bytes = sysconf(_SC_PAGESIZE); @@ -623,6 +623,7 @@ static unsigned long kb_inactive_file; void meminfo(void){ char namebuf[32]; /* big enough to hold any row name */ + int linux_version_code = procps_linux_version(); mem_table_struct findme = { namebuf, NULL}; mem_table_struct *found; char *head; diff --git a/proc/version.c b/proc/version.c index 88b6eeb4..a78f9377 100644 --- a/proc/version.c +++ b/proc/version.c @@ -1,9 +1,10 @@ /* - * Suite version information for procps-ng utilities - * Copyright (c) 1995 Martin Schulze - * Amended by cblake to only export the function symbol. + * libprocps - Library to read proc filesystem * - * Modified by Albert Cahalan, ????-2003 + * Copyright (C) 1995 Martin Schulze + * Copyright (C) 1996 Charles Blake + * Copyright (C) 2003 Albert Cahalan + * Copyright (C) 2015 Craig Small * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,59 +20,44 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - +#include #include -#include +#include "procps-private.h" #include "version.h" -/* Linux kernel version information for procps-ng utilities - * Copyright (c) 1996 Charles Blake - */ -#include - -#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) - -int linux_version_code; - -void init_Linux_version(void) { - int x = 0, y = 0, z = 0; /* cleared in case sscanf() < 3 */ - int version_string_depth; - -#ifdef __linux__ - static struct utsname uts; +#define PROCFS_OSRELEASE "/proc/sys/kernel/osrelease" - if (uname(&uts) == -1) /* failure implies impending death */ - exit(1); - - version_string_depth = sscanf(uts.release, "%d.%d.%d", &x, &y, &z); -#else +/* + * procps_linux_version + * + * Return the current running Linux version release as shown in + * the procps filesystem. + * + * There are three ways you can get OS release: + * 1) /proc/sys/kernel/osrelease - returns correct version of procfs + * 2) /proc/version - returns version of kernel e.g. BSD this is wrong + * 3) uname and uts.release - same as /proc/version field #3 + * + * Returns: version as an integer + * Negative value means an error + */ +PROCPS_EXPORT int procps_linux_version(void) +{ FILE *fp; char buf[256]; + unsigned int x = 0, y = 0, z = 0; + int version_string_depth; - if ( (fp=fopen("/proc/version","r")) == NULL) { - fprintf(stderr, "Cannot find /proc/version - is /proc mounted?\n"); - exit(1); - } + if ((fp = fopen(PROCFS_OSRELEASE, "r")) == NULL) + return -errno; if (fgets(buf, 256, fp) == NULL) { - fprintf(stderr, "Cannot read kernel version from /proc/version\n"); - fclose(fp); - exit(1); + fclose(fp); + return -EIO; } fclose(fp); - version_string_depth = sscanf(buf, "Linux version %d.%d.%d", &x, &y, &z); -#endif /* __linux__ */ - + version_string_depth = sscanf(buf, "%u.%u.%u", &x, &y, &z); if ((version_string_depth < 2) || /* Non-standard for all known kernels */ ((version_string_depth < 3) && (x < 3))) /* Non-standard for 2.x.x kernels */ -#ifdef __linux__ - fprintf(stderr, /* *very* unlikely to happen by accident */ - "Non-standard uts for running kernel:\n" - "release %s=%d.%d.%d gives version code %d\n", - uts.release, x, y, z, LINUX_VERSION(x,y,z)); -#else - fprintf(stderr, /* *very* unlikely to happen by accident */ - "%s=%d.%d.%d gives version code %d\n", - buf, x, y, z, LINUX_VERSION(x,y,z)); -#endif /* __linux__ */ - linux_version_code = LINUX_VERSION(x, y, z); + return -ERANGE; + return LINUX_VERSION(x,y,z); } diff --git a/proc/version.h b/proc/version.h index f1848ff0..e4dcef46 100644 --- a/proc/version.h +++ b/proc/version.h @@ -1,23 +1,33 @@ -#ifndef PROC_VERSION_H -#define PROC_VERSION_H - -#include "procps.h" - -/* Suite version information for procps-ng utilities - * Copyright (c) 1995 Martin Schulze - * Linux kernel version information for procps-ng utilities - * Copyright (c) 1996 Charles Blake - * Distributable under the terms of the GNU Library General Public License +/* + * libprocps - Library to read proc filesystem + * + * Copyright (C) 1995 Martin Schulze + * Copyright (C) 1996 Charles Blake + * Copyright (C) 2003 Albert Cahalan + * Copyright (C) 2015 Craig Small * - * Copyright 2002 Albert Cahalan + * 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 PROC_VERSION_H +#define PROC_VERSION_H -EXTERN_C_BEGIN - -void init_Linux_version(void); /* Get Linux version */ +#ifdef __cplusplus +extern "C" { +#endif -extern int linux_version_code; /* runtime version of LINUX_VERSION_CODE - in /usr/include/linux/version.h */ +int procps_linux_version(void); /* Convenience macros for composing/decomposing version codes */ #define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) @@ -25,6 +35,8 @@ extern int linux_version_code; /* runtime version of LINUX_VERSION_CODE #define LINUX_VERSION_MINOR(x) (((x)>> 8) & 0xFF) #define LINUX_VERSION_PATCH(x) ( (x) & 0xFF) -EXTERN_C_END +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* PROC_VERSION_H */ diff --git a/ps/global.c b/ps/global.c index 5abd3a26..91ca7426 100644 --- a/ps/global.c +++ b/ps/global.c @@ -455,6 +455,7 @@ static const char archdefs[] = /*********** spew variables ***********/ void self_info(void){ + int linux_version_code = procps_linux_version(); fprintf(stderr, "BSD j %s\n" "BSD l %s\n" diff --git a/top/top.c b/top/top.c index 891fd96a..16554be1 100644 --- a/top/top.c +++ b/top/top.c @@ -407,6 +407,7 @@ static void bye_bye (const char *str) { at_eoj(); // restore tty in preparation for exit #ifdef ATEOJ_RPTSTD { proc_t *p; + int linux_version_code = procps_linux_version(); if (!str && !Frames_signal && Ttychanged) { fprintf(stderr, "\n%s's Summary report:" "\n\tProgram" @@ -3263,6 +3264,7 @@ static void before (char *me) { struct sigaction sa; proc_t p; int i; + int linux_version_code = procps_linux_version(); atexit(close_stdout); -- 2.40.0