From 8e96493c4ea3a5c47819acf4a1153a0d802bd802 Mon Sep 17 00:00:00 2001 From: Sebastien Godard Date: Tue, 7 Feb 2012 22:14:12 +0100 Subject: [PATCH] iostat didn't display target device information when a symbolic link was specified as a parameter. This is now fixed. Mail from Peter Schiffer 30/01/2012 Hello Sebastien, my name is Peter Schiffer and I am a new maintainer of sysstat package in RHEL and Fedora. We have found the following issue: iostat does not display target device information when a symbolic link is specified as a parameter example: Linux 2.6.32-202.el6.x86_64 (localhost.localdomain) 11/30/11 _x86_64_ (16 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.04 0.00 0.05 0.04 0.00 99.87 Device: tps Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn I am proposing one solution how this could be fixed. What is your opinion about it? Thanks, peter symlinks.patch diff -upr sysstat-10.0.3.old/common.c sysstat-10.0.3/common.c --- sysstat-10.0.3.old/common.c 2011-11-20 16:38:04.000000000 +0100 +++ sysstat-10.0.3/common.c 2012-01-30 15:54:28.856597845 +0100 @@ -379,10 +379,10 @@ int get_win_height(void) /* *************************************************************************** - * Remove /dev from path name. + * Canonicalize and remove /dev from path name. * * IN: - * @name Device name (may begins with "/dev/") + * @name Device name (may begins with "/dev/" or can be a symlink) * * RETURNS: * Device basename. @@ -390,10 +390,33 @@ int get_win_height(void) */ char *device_name(char *name) { - if (!strncmp(name, "/dev/", 5)) - return name + 5; + char *out; + char *resolved_name; - return name; + /* realpath() creates new string, so we need to free it later. */ + resolved_name = realpath(name, 0); + + /* If path doesn't exists, just copy the input and return it. We have to + copy because result of this function is always freed. */ + if (!resolved_name) { + out = (char *)calloc(1, sizeof(name)); + strncpy(out, name, sizeof(name)); + + return out; + } + + /* We need to copy the path without "/dev/" prefix because we cannot free + 'resolved_name + 5' string. */ + if (!strncmp(resolved_name, "/dev/", 5)) { + out = (char *)calloc(1, sizeof(resolved_name) - 4); + strncpy(out, resolved_name + 5, sizeof(resolved_name) - 4); + + free(resolved_name); + + return out; + } + + return resolved_name; } /* diff -upr sysstat-10.0.3.old/iostat.c sysstat-10.0.3/iostat.c --- sysstat-10.0.3.old/iostat.c 2011-11-20 16:38:04.000000000 +0100 +++ sysstat-10.0.3/iostat.c 2012-01-30 15:57:41.551553692 +0100 @@ -274,6 +274,8 @@ int update_dev_list(int *dlist_idx, char strncpy(sdli->dev_name, device_name, MAX_NAME_LEN - 1); } + free(device_name); + return i; } --- CHANGES | 3 +++ CREDITS | 1 + common.c | 29 +++++++++++++++++++++++------ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 66f81ab..f7183d6 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,9 @@ Changes: xxxx/xx/xx: Version 10.0.4 - Sebastien Godard (sysstat orange.fr) * [Andrey Borzenkov]: Don't take virtual devices into account in sar -b results. + * [Peter Schiffer]: iostat didn't display target device + information when a symbolic link was specified as a parameter. + This is now fixed. * configure script updated: Added --disable-stripping option. Using this option tells configure to NOT strip object files. * FAQ updated. diff --git a/CREDITS b/CREDITS index 918a943..383b66d 100644 --- a/CREDITS +++ b/CREDITS @@ -198,6 +198,7 @@ I would also thank the following people for their hints or bug reports Tan Shao Yi Yibin Shen Lee Schermerhorn + Peter Schiffer Benno Schulenberg Michel Simoni Gabrielle Singleton diff --git a/common.c b/common.c index dad20c6..2e3aa70 100644 --- a/common.c +++ b/common.c @@ -1,6 +1,6 @@ /* * sar, sadc, sadf, mpstat and iostat common routines. - * (C) 1999-2011 by Sebastien GODARD (sysstat orange.fr) + * (C) 1999-2012 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * @@ -379,10 +379,10 @@ int get_win_height(void) /* *************************************************************************** - * Remove /dev from path name. + * Canonicalize and remove /dev from path name. * * IN: - * @name Device name (may begins with "/dev/") + * @name Device name (may begin with "/dev/" or can be a symlink). * * RETURNS: * Device basename. @@ -390,10 +390,27 @@ int get_win_height(void) */ char *device_name(char *name) { - if (!strncmp(name, "/dev/", 5)) - return name + 5; + static char out[MAX_FILE_LEN]; + char *resolved_name; + int i = 0; - return name; + /* realpath() creates new string, so we need to free it later */ + resolved_name = realpath(name, NULL); + + /* If path doesn't exist, just return input */ + if (!resolved_name) { + return name; + } + + if (!strncmp(resolved_name, "/dev/", 5)) { + i = 5; + } + strncpy(out, resolved_name + i, MAX_FILE_LEN); + out[MAX_FILE_LEN - 1] = '\0'; + + free(resolved_name); + + return out; } /* -- 2.40.0