link was specified as a parameter. This is now fixed.
Mail from Peter Schiffer <pschiffe@redhat.com> 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;
}
xxxx/xx/xx: Version 10.0.4 - Sebastien Godard (sysstat <at> 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.
Tan Shao Yi <tansy@tan[...].org>
Yibin Shen <zituan@taobao.com>
Lee Schermerhorn <lee.schermerhorn@hp.[...].com>
+ Peter Schiffer <pschiffe@red[...].com>
Benno Schulenberg <bensberg@jus[...].net>
Michel Simoni <m_simoni@clu[...].fr>
Gabrielle Singleton <gelle@umi[...].edu>
/*
* sar, sadc, sadf, mpstat and iostat common routines.
- * (C) 1999-2011 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 1999-2012 by Sebastien GODARD (sysstat <at> orange.fr)
*
***************************************************************************
* This program is free software; you can redistribute it and/or modify it *
/*
***************************************************************************
- * 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.
*/
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;
}
/*