summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoît Dejean <bdejean@src.gnome.org>2007-05-13 08:20:10 +0000
committerBenoît Dejean <bdejean@src.gnome.org>2007-05-13 08:20:10 +0000
commit3eb958dc6cb4a9247661c4444189e7f2c1597db9 (patch)
tree8632270dca3380fbbf13cd310e5b867a06c22a33
parentcd389851b961691507d80968d64d9e275350a7b4 (diff)
downloadlibgtop-3eb958dc6cb4a9247661c4444189e7f2c1597db9.tar.gz
Manual commit from my local git-svn which is broken :/
svn path=/trunk/; revision=2578
-rw-r--r--ChangeLog20
-rw-r--r--configure.in14
-rw-r--r--features.def1
-rw-r--r--include/glibtop/Makefile.am1
-rw-r--r--include/glibtop/command.h3
-rw-r--r--include/glibtop/sysdeps.h4
-rw-r--r--include/glibtop/union.h2
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/sysdeps.c7
-rw-r--r--src/daemon/Makefile.am3
-rw-r--r--src/daemon/daemon.h4
-rw-r--r--src/daemon/gnuserv.c65
-rw-r--r--src/daemon/main.c9
-rw-r--r--src/daemon/server.c2
-rw-r--r--sysdeps/bsd/ChangeLog8
-rw-r--r--sysdeps/bsd/fsusage.c2
-rw-r--r--sysdeps/bsd/netload.c4
-rw-r--r--sysdeps/common/default.c14
-rw-r--r--sysdeps/linux/ChangeLog26
-rw-r--r--sysdeps/linux/Makefile.am2
-rw-r--r--sysdeps/linux/glibtop_private.c17
-rw-r--r--sysdeps/linux/glibtop_private.h2
-rw-r--r--sysdeps/linux/glibtop_server.h1
-rw-r--r--sysdeps/linux/procopenfiles.c5
24 files changed, 161 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index f596fc22..9cd6764f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2007-05-10 Benoît Dejean <benoit@placenet.org>
+
+ * lib/libgtop.sym:
+
+ Added missing *_p symbols.
+
+2007-05-07 Benoît Dejean <benoit@placenet.org>
+
+ * configure.in:
+ * lib/Makefile.am:
+ * lib/libgtop.sym:
+
+ Updated libtool version.
+ Now uses a symbol list instead of a regex.
+
+2007-05-07 Benoît Dejean <benoit@placenet.org>
+
+ * New API to get cwd, root and exe path
+ of a process. API not frozen yet.
+
2007-04-27 Benoît Dejean <benoit@placenet.org>
Got rid of InodeDB.
diff --git a/configure.in b/configure.in
index 3e544364..25dbe5cf 100644
--- a/configure.in
+++ b/configure.in
@@ -8,16 +8,16 @@ m4_define([libgtop_micro_version], [1])
m4_define([libgtop_version], [libgtop_major_version.libgtop_minor_version.libgtop_micro_version])
dnl increment if the interface has additions, changes, removals.
-m4_define([libgtop_current], [7])
+m4_define([libgtop_current], [8])
dnl increment any time the source changes; set to
dnl 0 if you increment CURRENT
-m4_define([libgtop_revision], [1])
+m4_define([libgtop_revision], [0])
dnl increment if any interfaces have been added; set to 0
dnl if any interfaces have been removed. removal has
dnl precedence over adding, so set to 0 if both happened.
-m4_define([libgtop_age], [0])
+m4_define([libgtop_age], [1])
# Increase each time you change the client/server protocol.
m4_define([libgtop_server_version], [5])
@@ -93,14 +93,6 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= $GLIB_REQUIRED)
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
-AC_CHECK_HEADER(popt.h,[POPT=yes],[POPT=no])
-AC_MSG_CHECKING(for popt.h)
-if test x$POPT = xyes ; then
- AC_MSG_RESULT(yes)
-else
- AC_MSG_ERROR([libgtop requires the popt development libraries])
-fi
-
AC_CHECK_HEADER(ifaddrs.h, [HAVE_IFADDRS_H=yes], [HAVE_IFADDRS_H=no])
if test x$HAVE_IFADDRS_H = xyes ; then
AC_DEFINE(HAVE_IFADDRS_H, 1, [defined if you have ifaddrs.h])
diff --git a/features.def b/features.def
index bb46c8d6..0936c98f 100644
--- a/features.def
+++ b/features.def
@@ -22,4 +22,5 @@ void|@fsusage|ulong(blocks,bfree,bavail,files,ffree)|string|mount_dir
void|netload|ulong(if_flags,mtu,subnet,address,packets_in,packets_out,packets_total,bytes_in,bytes_out,bytes_total,errors_in,errors_out,errors_total,collisions)|string|interface
void|ppp|ulong(state,bytes_in,bytes_out)|ushort(device)
char **|netlist|unsigned(number)
+char **|proc_wd|ulong(number),str(root),str(exe)|pid_t(pid)
diff --git a/include/glibtop/Makefile.am b/include/glibtop/Makefile.am
index 2b4df591..89544251 100644
--- a/include/glibtop/Makefile.am
+++ b/include/glibtop/Makefile.am
@@ -8,6 +8,7 @@ glibtop_HEADERS = close.h loadavg.h prockernel.h procstate.h \
procsignal.h union.h gnuserv.h \
parameter.h mountlist.h fsusage.h procmap.h signal.h \
sysinfo.h ppp.h procargs.h netload.h \
+ procwd.h
netlist.h procopenfiles.h open.h
noinst_HEADERS = error.h write.h read_data.h read.h init_hooks.h
diff --git a/include/glibtop/command.h b/include/glibtop/command.h
index 92ad02fa..bd9667e8 100644
--- a/include/glibtop/command.h
+++ b/include/glibtop/command.h
@@ -57,8 +57,9 @@ G_BEGIN_DECLS
#define GLIBTOP_CMND_PPP 23
#define GLIBTOP_CMND_NETLIST 24
#define GLIBTOP_CMND_PROC_OPEN_FILES 25
+#define GLIBTOP_CMND_PROC_WD 26
-#define GLIBTOP_MAX_CMND 26
+#define GLIBTOP_MAX_CMND 27
#define _GLIBTOP_PARAM_SIZE 16
diff --git a/include/glibtop/sysdeps.h b/include/glibtop/sysdeps.h
index 76dd7161..40f0b6b2 100644
--- a/include/glibtop/sysdeps.h
+++ b/include/glibtop/sysdeps.h
@@ -51,8 +51,9 @@ G_BEGIN_DECLS
#define GLIBTOP_SYSDEPS_PPP 22
#define GLIBTOP_SYSDEPS_NETLIST 23
#define GLIBTOP_SYSDEPS_PROC_OPEN_FILES 24
+#define GLIBTOP_SYSDEPS_PROC_WD 25
-#define GLIBTOP_MAX_SYSDEPS 25
+#define GLIBTOP_MAX_SYSDEPS 26
#define GLIBTOP_SYSDEPS_ALL ((1 << GLIBTOP_MAX_SYSDEPS) - 1)
@@ -86,6 +87,7 @@ struct _glibtop_sysdeps
guint64 netlist; /* glibtop_netlist */
guint64 netload; /* glibtop_netload */
guint64 ppp; /* glibtop_ppp */
+ guint64 proc_wd; /* glibtop_proc_wd */
};
void glibtop_get_sysdeps (glibtop_sysdeps *buf);
diff --git a/include/glibtop/union.h b/include/glibtop/union.h
index b53b5694..39da4640 100644
--- a/include/glibtop/union.h
+++ b/include/glibtop/union.h
@@ -42,6 +42,7 @@
#include <glibtop/procargs.h>
#include <glibtop/procmap.h>
#include <glibtop/procopenfiles.h>
+#include <glibtop/procwd.h>
#include <glibtop/mountlist.h>
#include <glibtop/fsusage.h>
@@ -80,6 +81,7 @@ union _glibtop_union
glibtop_netload netload;
glibtop_ppp ppp;
glibtop_proc_open_files proc_open_files;
+ glibtop_proc_wd proc_wd;
};
G_END_DECLS
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8338d54a..926a5bff 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,7 +7,7 @@ libgtop_2_0_la_SOURCES = init.c open.c close.c command.c read.c \
read_data.c write.c lib.c parameter.c \
sysdeps.c
-libgtop_2_0_la_LDFLAGS = $(LT_VERSION_INFO) -export-symbols-regex "^[^_].*"
+libgtop_2_0_la_LDFLAGS = $(LT_VERSION_INFO) -export-symbols $(top_builddir)/lib/libgtop.sym
libgtop_2_0_la_LIBADD = $(GLIB_LIBS) $(top_builddir)/sysdeps/common/libgtop_common-2.0.la $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps-2.0.la $(sysdeps_suid_lib)
BUILT_SOURCES = lib.c
diff --git a/lib/sysdeps.c b/lib/sysdeps.c
index f008eb6c..1540a601 100644
--- a/lib/sysdeps.c
+++ b/lib/sysdeps.c
@@ -46,6 +46,7 @@ GLIBTOP_SUID_PROC_ARGS +
GLIBTOP_SUID_PROC_MAP +
GLIBTOP_SUID_NETLOAD +
GLIBTOP_SUID_NETLIST +
+GLIBTOP_SUID_PROC_WD +
GLIBTOP_SUID_PPP;
const _glibtop_init_func_t _glibtop_init_hook_s [] = {
@@ -109,6 +110,9 @@ const _glibtop_init_func_t _glibtop_init_hook_s [] = {
#if !GLIBTOP_SUID_NETLIST
_glibtop_init_netlist_s,
#endif
+#if !GLIBTOP_SUID_PROC_WD
+ _glibtop_init_proc_wd_s,
+#endif
#if !GLIBTOP_SUID_PPP
_glibtop_init_ppp_s,
#endif
@@ -176,6 +180,9 @@ const _glibtop_init_func_t _glibtop_init_hook_p [] = {
#if GLIBTOP_SUID_NETLIST
_glibtop_init_netlist_p,
#endif
+#if GLIBTOP_SUID_PROC_WD
+ _glibtop_init_proc_wd_p,
+#endif
#if GLIBTOP_SUID_PPP
_glibtop_init_ppp_p,
#endif
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 11c310d5..4462bb6e 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -40,11 +40,10 @@ libgtop_daemon2_LDADD = $(top_builddir)/lib/libgtop-2.0.la \
@sysdeps_suid_lib@ \
$(suid_sysdeps) $(suid_common) \
$(LIBGTOP_LIBS) \
- -lpopt \
@libs_xauth@
libgtop_server2_SOURCES = server.c slave.c io.c version.c daemon.h
-libgtop_server2_LDADD = $(GLIB_LIBS) -lpopt $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps_suid-2.0.la \
+libgtop_server2_LDADD = $(GLIB_LIBS) $(top_builddir)/sysdeps/@sysdeps_dir@/libgtop_sysdeps_suid-2.0.la \
$(top_builddir)/sysdeps/common/libgtop_suid_common-2.0.la
EXTRA_DIST = server_config.h.in server_config.pl
diff --git a/src/daemon/daemon.h b/src/daemon/daemon.h
index 23ee5f21..cd9520be 100644
--- a/src/daemon/daemon.h
+++ b/src/daemon/daemon.h
@@ -69,8 +69,8 @@ int do_read (int s, void *ptr, size_t total_size) G_GNUC_INTERNAL;
void syslog_message (int priority, const char *format, ...) G_GNUC_INTERNAL G_GNUC_PRINTF(2, 3);
void syslog_io_message (int priority, const char *format, ...) G_GNUC_INTERNAL G_GNUC_PRINTF(2, 3);
-extern int enable_debug;
-extern int verbose_output;
+extern gboolean enable_debug;
+extern gboolean verbose_output;
G_END_DECLS
diff --git a/src/daemon/gnuserv.c b/src/daemon/gnuserv.c
index ea61ded1..8243b871 100644
--- a/src/daemon/gnuserv.c
+++ b/src/daemon/gnuserv.c
@@ -46,7 +46,6 @@
#include <glibtop/gnuserv.h>
#include <errno.h>
-#include <popt.h>
#include "daemon.h"
@@ -79,10 +78,10 @@ static Xauth *server_xauth = NULL;
#endif /* AUTH_MAGIC_COOKIE */
-int enable_debug = 0;
-int verbose_output = 0;
-static int no_daemon = 0;
-static int invoked_from_inetd = 0;
+gboolean enable_debug = FALSE;
+gboolean verbose_output = FALSE;
+static gboolean no_daemon = FALSE;
+static gboolean invoked_from_inetd = FALSE;
static int changed_uid = 0;
void
@@ -454,27 +453,26 @@ handle_signal (int sig)
exit (1);
}
-const struct poptOption popt_options [] = {
- POPT_AUTOHELP
- { "debug", 'd', POPT_ARG_NONE, &enable_debug, 0,
- N_("Enable debugging"), N_("DEBUG") },
- { "verbose", 'v', POPT_ARG_NONE, &verbose_output, 0,
- N_("Enable verbose output"), N_("VERBOSE") },
- { "no-daemon", 'f', POPT_ARG_NONE, &no_daemon, 0,
- N_("Don't fork into background"), N_("NO-DAEMON") },
- { "inetd", 'i', POPT_ARG_NONE, &invoked_from_inetd, 0,
- N_("Invoked from inetd"), N_("INETD") },
- { NULL, '\0', 0, NULL, 0, NULL, NULL }
+static const GOptionEntry options [] = {
+ { "debug", 'd', 0, G_OPTION_ARG_NONE, &enable_debug,
+ N_("Enable debugging"), NULL },
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose_output,
+ N_("Enable verbose output"), NULL },
+ { "no-daemon", 'f', 0, G_OPTION_ARG_NONE, &no_daemon,
+ N_("Don't fork into background"), NULL },
+ { "inetd", 'i', 0, G_OPTION_ARG_NONE, &invoked_from_inetd,
+ N_("Invoked from inetd"), NULL },
+ { NULL }
};
int
-main (int argc, const char **argv)
+main (int argc, char **argv)
{
const unsigned method = GLIBTOP_METHOD_PIPE;
const unsigned long features = GLIBTOP_SYSDEPS_ALL;
glibtop *server = glibtop_global_server;
- poptContext context;
- int nextopt;
+ GOptionContext *goption_context;
+ GError *error = NULL;
int ils = -1; /* internet domain listen socket */
@@ -488,22 +486,19 @@ main (int argc, const char **argv)
arg ? (arg + 1) : program_invocation_name;
}
- context = poptGetContext ("libgtop-daemon", argc, argv,
- popt_options, 0);
-
- poptReadDefaultConfig (context, TRUE);
-
- while ((nextopt = poptGetNextOpt (context)) > 0)
- /* do nothing */ ;
-
- if(nextopt != -1) {
- printf (_("Error on option %s: %s.\n"
- "Run '%s --help' to see a full list of "
- "available command line options.\n"),
- poptBadOption (context, 0),
- poptStrerror (nextopt),
- argv[0]);
- exit(1);
+ g_set_prgname (program_invocation_short_name);
+ goption_context = g_option_context_new (NULL);
+ g_option_context_add_main_entries (goption_context, options, NULL);
+ g_option_context_parse (goption_context, &argc, &argv, &error);
+ g_option_context_free (goption_context);
+
+ if (error != NULL) {
+ g_printerr ("%s\n", error->message);
+ g_error_free (error);
+ g_printerr (_("Run '%s --help' to see a full list of "
+ "available command line options.\n"),
+ program_invocation_name);
+ exit(1);
}
if (enable_debug)
diff --git a/src/daemon/main.c b/src/daemon/main.c
index a4a2f9b6..713adabc 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -150,6 +150,15 @@ handle_parent_connection (int s)
resp->u.data.proc_map.total, ptr);
g_free (ptr);
break;
+
+ case GLIBTOP_CMND_PROC_WD:
+ /* FIXME */
+ break;
+
+ case GLIBTOP_CMND_NETLIST:
+ /* FIXME */
+ break;
+
case GLIBTOP_CMND_PROC_ARGS:
memcpy (&pid, parameter, sizeof (pid_t));
ptr = glibtop_get_proc_args_l (server,
diff --git a/src/daemon/server.c b/src/daemon/server.c
index c639e2e6..9af133c0 100644
--- a/src/daemon/server.c
+++ b/src/daemon/server.c
@@ -51,6 +51,8 @@ GLIBTOP_SUID_PROC_SEGMENT +
GLIBTOP_SUID_PROC_ARGS +
GLIBTOP_SUID_PROC_MAP +
GLIBTOP_SUID_NETLOAD +
+GLIBTOP_SUID_NETLIST +
+GLIBTOP_SUID_PROC_WD +
GLIBTOP_SUID_PPP;
#include <fcntl.h>
diff --git a/sysdeps/bsd/ChangeLog b/sysdeps/bsd/ChangeLog
index 9b92d189..abac6dbe 100644
--- a/sysdeps/bsd/ChangeLog
+++ b/sysdeps/bsd/ChangeLog
@@ -1,3 +1,11 @@
+2007-05-08 Benoît Dejean <benoit@placenet.org>
+
+ * fsusage.c: (_glibtop_bsd_get_fsusage_read_write):
+ * netload.c: (glibtop_get_netload_p):
+
+ Fixed build on OpenBSD.
+ Patch by Jasper Lievisse Adriaanse <jasper@nedbsd.nl>.
+
2007-02-18 Benoît Dejean <benoit@placenet.org>
* AUTHORS:
diff --git a/sysdeps/bsd/fsusage.c b/sysdeps/bsd/fsusage.c
index 5f592b5d..db337153 100644
--- a/sysdeps/bsd/fsusage.c
+++ b/sysdeps/bsd/fsusage.c
@@ -54,7 +54,9 @@ _glibtop_bsd_get_fsusage_read_write(glibtop *server,
return;
}
+#if !defined(__OpenBSD__)
buf->read = sfs.f_syncreads + sfs.f_asyncreads;
+#endif
buf->write = sfs.f_syncwrites + sfs.f_asyncwrites;
buf->flags |= (1 << GLIBTOP_FSUSAGE_READ) | (1 << GLIBTOP_FSUSAGE_WRITE);
}
diff --git a/sysdeps/bsd/netload.c b/sysdeps/bsd/netload.c
index 6dd1a6d6..a16bdd0b 100644
--- a/sysdeps/bsd/netload.c
+++ b/sysdeps/bsd/netload.c
@@ -233,7 +233,11 @@ glibtop_get_netload_p (glibtop *server, glibtop_netload *buf,
buf->flags |= GLIBTOP_NETLOAD_ADDRESS6;
}
/* FIXME prefix6, scope6 */
+#if defined (__OpenBSD__)
+ ifaddraddr = (u_long) ifaddr.ifa.ifa_list.tqe_next;
+#else
ifaddraddr = (u_long) ifaddr.ifa.ifa_link.tqe_next;
+#endif
}
return;
}
diff --git a/sysdeps/common/default.c b/sysdeps/common/default.c
index ff734ec5..d24b52a0 100644
--- a/sysdeps/common/default.c
+++ b/sysdeps/common/default.c
@@ -352,5 +352,19 @@ glibtop_get_sysdeps(glibtop_sysdeps *buf)
}
+/**
+ * glibtop_get_proc_wd:
+ * @buf:
+ * @pid: Process id to get the user and tty information
+ *
+ * Get the root directory and the working directories
+ *
+ * Returns: A NULL-terminated list of working directories.
+ */
+char**
+glibtop_get_proc_wd(glibtop_proc_wd *buf, pid_t pid)
+{
+ return glibtop_get_proc_wd_l(glibtop_global_server, buf, pid);
+}
diff --git a/sysdeps/linux/ChangeLog b/sysdeps/linux/ChangeLog
index 29d881f3..2b91dd43 100644
--- a/sysdeps/linux/ChangeLog
+++ b/sysdeps/linux/ChangeLog
@@ -1,3 +1,29 @@
+2007-05-07 Benoît Dejean <benoit@placenet.org>
+
+ * procwd.c:
+
+ Always set buf->number.
+
+2007-05-07 Benoît Dejean <benoit@placenet.org>
+
+ * glibtop_private.c (safe_readlink):
+
+ Simplified.
+
+ * procopenfiles.c:
+
+ Use safe_readlink.
+
+2007-05-07 Benoît Dejean <benoit@placenet.org>
+
+ * procwd.c:
+
+ Implemented.
+
+ * glibtop_private.c (safe_readlink):
+
+ New function.
+
2007-03-13 Benoît Dejean <benoit@placenet.org>
* fsusage.c: (get_sys_path), (linux_2_6_0):
diff --git a/sysdeps/linux/Makefile.am b/sysdeps/linux/Makefile.am
index ae62023d..6b94337b 100644
--- a/sysdeps/linux/Makefile.am
+++ b/sysdeps/linux/Makefile.am
@@ -8,7 +8,7 @@ libgtop_sysdeps_2_0_la_SOURCES = open.c close.c cpu.c mem.c swap.c \
proctime.c procmem.c procsignal.c prockernel.c \
procsegment.c procargs.c procmap.c siglist.c \
sysinfo.c netload.c ppp.c glibtop_private.c \
- fsusage.c netlist.c procopenfiles.c
+ fsusage.c netlist.c procopenfiles.c procwd.c
libgtop_sysdeps_2_0_la_LIBADD = @GLIB_LIBS@
diff --git a/sysdeps/linux/glibtop_private.c b/sysdeps/linux/glibtop_private.c
index e93f8397..8526f694 100644
--- a/sysdeps/linux/glibtop_private.c
+++ b/sysdeps/linux/glibtop_private.c
@@ -184,3 +184,20 @@ has_sysfs(void)
return sysfs;
}
+
+
+
+gboolean safe_readlink(const char *path, char *buf, size_t bufsiz)
+{
+ ssize_t ret;
+
+ ret = readlink(path, buf, bufsiz - 1);
+
+ if (ret == -1) {
+ g_warning("Could not read link %s : %s", path, strerror(errno));
+ return FALSE;
+ }
+
+ buf[ret] = '\0';
+ return TRUE;
+}
diff --git a/sysdeps/linux/glibtop_private.h b/sysdeps/linux/glibtop_private.h
index 30f53960..74cd2737 100644
--- a/sysdeps/linux/glibtop_private.h
+++ b/sysdeps/linux/glibtop_private.h
@@ -145,6 +145,8 @@ check_cpu_line_warn(glibtop *server, const char *line, unsigned i)
gboolean
has_sysfs(void) G_GNUC_INTERNAL G_GNUC_CONST;
+gboolean safe_readlink(const char *path, char *buf, size_t bufsiz);
+
G_END_DECLS
diff --git a/sysdeps/linux/glibtop_server.h b/sysdeps/linux/glibtop_server.h
index c00e513f..3f9980d6 100644
--- a/sysdeps/linux/glibtop_server.h
+++ b/sysdeps/linux/glibtop_server.h
@@ -42,6 +42,7 @@
#define GLIBTOP_SUID_PROC_MAP 0
#define GLIBTOP_SUID_NETLOAD 0
#define GLIBTOP_SUID_NETLIST 0
+#define GLIBTOP_SUID_PROC_WD 0
#define GLIBTOP_SUID_PPP 0
#define GLIBTOP_SUID_PROC_FILE 0
diff --git a/sysdeps/linux/procopenfiles.c b/sysdeps/linux/procopenfiles.c
index 1f4b6474..e1acad55 100644
--- a/sysdeps/linux/procopenfiles.c
+++ b/sysdeps/linux/procopenfiles.c
@@ -204,9 +204,8 @@ glibtop_get_proc_open_files_s (glibtop *server, glibtop_proc_open_files *buf, pi
g_snprintf(fn, sizeof fn, "/proc/%d/fd/%s",
pid, direntry->d_name);
- rv = readlink(fn, tgt, sizeof(tgt) - 1);
- if(rv < 0) continue;
- tgt[rv] = '\0';
+ if (!safe_readlink(fn, tgt, tgt))
+ continue;
entry.fd = atoi(direntry->d_name);