vppinfra: add clib_file_get_resolved_basename

more generic version of clib_sysfs_link_to_name with support for
format strings...

Type: improvement
Change-Id: I0cb263748970378c661415196eb7e08450370677
Signed-off-by: Damjan Marion <damarion@cisco.com>
diff --git a/src/plugins/rdma/device.c b/src/plugins/rdma/device.c
index b1a4d35..8aeb586 100644
--- a/src/plugins/rdma/device.c
+++ b/src/plugins/rdma/device.c
@@ -882,7 +882,7 @@
   unformat_input_t in;
   u8 *s;
 
-  s = clib_sysfs_link_to_name (path);
+  s = clib_file_get_resolved_basename (path);
   if (!s)
     return 0;
 
diff --git a/src/vlib/linux/pci.c b/src/vlib/linux/pci.c
index e94fee1..9661827 100644
--- a/src/vlib/linux/pci.c
+++ b/src/vlib/linux/pci.c
@@ -293,16 +293,13 @@
     goto error;
   di->revision = tmp;
 
-  vec_reset_length (f);
-  f = format (f, "%v/driver%c", dev_dir_name, 0);
-  di->driver_name = clib_sysfs_link_to_name ((char *) f);
+  di->driver_name =
+    clib_file_get_resolved_basename ("%v/driver", dev_dir_name);
   if (!di->driver_name)
     di->driver_name = format (0, "<NONE>%c", 0);
 
   di->iommu_group = -1;
-  vec_reset_length (f);
-  f = format (f, "%v/iommu_group%c", dev_dir_name, 0);
-  tmpstr = clib_sysfs_link_to_name ((char *) f);
+  tmpstr = clib_file_get_resolved_basename ("%v/iommu_group", dev_dir_name);
   if (tmpstr)
     {
       di->iommu_group = atoi ((char *) tmpstr);
@@ -506,9 +503,7 @@
 	}
     }
 
-  s = format (s, "%v/driver%c", dev_dir_name, 0);
-  driver_name = clib_sysfs_link_to_name ((char *) s);
-  vec_reset_length (s);
+  driver_name = clib_file_get_resolved_basename ("%v/driver", dev_dir_name);
 
   if (driver_name &&
       ((strcmp ("vfio-pci", (char *) driver_name) == 0) ||
diff --git a/src/vlib/linux/vfio.c b/src/vlib/linux/vfio.c
index dc68c52..ee04081 100644
--- a/src/vlib/linux/vfio.c
+++ b/src/vlib/linux/vfio.c
@@ -185,10 +185,8 @@
   int fd;
 
   *is_noiommu = 0;
-  s =
-    format (s, "/sys/bus/pci/devices/%U/iommu_group%c", format_vlib_pci_addr,
-	    addr, 0);
-  tmpstr = clib_sysfs_link_to_name ((char *) s);
+  tmpstr = clib_file_get_resolved_basename (
+    "/sys/bus/pci/devices/%U/iommu_group", format_vlib_pci_addr, addr);
   if (tmpstr)
     {
       iommu_group = atoi ((char *) tmpstr);
diff --git a/src/vlib/linux/vmbus.c b/src/vlib/linux/vmbus.c
index aae11a1..b066381 100644
--- a/src/vlib/linux/vmbus.c
+++ b/src/vlib/linux/vmbus.c
@@ -253,16 +253,14 @@
   static int uio_new_id_needed = 1;
   struct dirent *e;
   struct ifreq ifr;
-  u8 *s, *driver_name;
+  u8 *s = 0, *driver_name;
   DIR *dir;
   int fd;
 
   dev_dir_name = format (0, "%s/%U", sysfs_vmbus_dev_path,
 			 format_vlib_vmbus_addr, addr);
-  s = format (0, "%v/driver%c", dev_dir_name, 0);
 
-  driver_name = clib_sysfs_link_to_name ((char *) s);
-  vec_reset_length (s);
+  driver_name = clib_file_get_resolved_basename ("%v/driver", dev_dir_name);
 
   /* skip if not using the Linux kernel netvsc driver */
   if (!driver_name || strcmp ("hv_netvsc", (char *) driver_name) != 0)
diff --git a/src/vppinfra/file.h b/src/vppinfra/file.h
index 09dd2fd..7195613 100644
--- a/src/vppinfra/file.h
+++ b/src/vppinfra/file.h
@@ -163,6 +163,8 @@
   return f->write_function (f);
 }
 
+u8 *clib_file_get_resolved_basename (char *fmt, ...);
+
 #endif /* included_clib_file_h */
 
 /*
diff --git a/src/vppinfra/linux/sysfs.c b/src/vppinfra/linux/sysfs.c
index a3e122c..6d9f859 100644
--- a/src/vppinfra/linux/sysfs.c
+++ b/src/vppinfra/linux/sysfs.c
@@ -87,32 +87,6 @@
   return 0;
 }
 
-__clib_export u8 *
-clib_sysfs_link_to_name (char *link)
-{
-  char *p, buffer[64];
-  unformat_input_t in;
-  u8 *s = 0;
-  int r;
-
-  r = readlink (link, buffer, sizeof (buffer) - 1);
-
-  if (r < 0)
-    return 0;
-
-  buffer[r] = 0;
-  p = strrchr (buffer, '/');
-
-  if (!p)
-    return 0;
-
-  unformat_init_string (&in, p + 1, strlen (p + 1));
-  if (unformat (&in, "%s", &s) != 1)
-    clib_unix_warning ("no string?");
-  unformat_free (&in);
-
-  return s;
-}
 
 clib_error_t *
 clib_sysfs_set_nr_hugepages (int numa_node, int log2_page_size, int nr)
diff --git a/src/vppinfra/linux/sysfs.h b/src/vppinfra/linux/sysfs.h
index 9cbc348..a616fa4 100644
--- a/src/vppinfra/linux/sysfs.h
+++ b/src/vppinfra/linux/sysfs.h
@@ -22,8 +22,6 @@
 
 clib_error_t *clib_sysfs_read (char *file_name, char *fmt, ...);
 
-u8 *clib_sysfs_link_to_name (char *link);
-
 clib_error_t *clib_sysfs_set_nr_hugepages (int numa_node,
 					   int log2_page_size, int nr);
 clib_error_t *clib_sysfs_get_nr_hugepages (int numa_node,
diff --git a/src/vppinfra/unix-misc.c b/src/vppinfra/unix-misc.c
index e73d01a..0c5d96c 100644
--- a/src/vppinfra/unix-misc.c
+++ b/src/vppinfra/unix-misc.c
@@ -38,12 +38,14 @@
 #include <vppinfra/error.h>
 #include <vppinfra/os.h>
 #include <vppinfra/unix.h>
+#include <vppinfra/format.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/uio.h>		/* writev */
 #include <fcntl.h>
 #include <stdio.h>		/* for sprintf */
+#include <limits.h>
 
 __clib_export __thread uword __os_thread_index = 0;
 __clib_export __thread uword __os_numa_index = 0;
@@ -131,6 +133,35 @@
   return error;
 }
 
+__clib_export u8 *
+clib_file_get_resolved_basename (char *fmt, ...)
+{
+  va_list va;
+  char *p, buffer[PATH_MAX];
+  u8 *link, *s = 0;
+  int r;
+
+  va_start (va, fmt);
+  link = va_format (0, fmt, &va);
+  va_end (va);
+  vec_add1 (link, 0);
+
+  r = readlink ((char *) link, buffer, sizeof (buffer) - 1);
+  vec_free (link);
+
+  if (r < 1)
+    return 0;
+
+  p = buffer + r - 1;
+  while (p > buffer && p[-1] != '/')
+    p--;
+
+  while (p[0])
+    vec_add1 (s, p++[0]);
+
+  return s;
+}
+
 clib_error_t *
 unix_proc_file_contents (char *file, u8 ** result)
 {