[PATCH] Finish the task 'sysctl reporting current working directory'

Tiwei Bie btw at mail.ustc.edu.cn
Thu Nov 6 11:40:01 UTC 2014


On Thu, Nov 06, 2014 at 12:13:58PM +0100, Mateusz Guzik wrote:
> On Thu, Nov 06, 2014 at 06:00:32PM +0800, Tiwei Bie wrote:
> > On Thu, Nov 06, 2014 at 11:21:34AM +0200, Konstantin Belousov wrote:
> > > On Thu, Nov 06, 2014 at 04:57:50PM +0800, Tiwei Bie wrote:
> > > > On Thu, Nov 06, 2014 at 09:13:31AM +0100, Mateusz Guzik wrote:
> > > > > On Mon, Nov 03, 2014 at 04:52:35PM +0800, Tiwei Bie wrote:
> > > > > 
> > > > > kernel changes got in in r274167
> > > > > 
> > > > > Please submit tmux patch to bugzilla.
> > > > > 
> > > > 
> > > > Thanks! I have submitted the tmux patch to bugzilla [1].
> > > > 
> > > > [1] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194858
> > > 
> > > This is incorrect way to use kern_proc_cwd.  You should try the new
> > > sysctl, and on ENOENT fall back to the kern_proc_file.  Expecting
> > > that the binary is run on the same machine where it was build is
> > > wrong.
> > > 
> > 
> > Yeah, you are right. Following is my new patch, maybe it needs some
> > style improvements.
> > 
> > diff --git a/osdep-freebsd.c b/osdep-freebsd.c
> > index d596eab..673ca98 100644
> > --- a/osdep-freebsd.c
> > +++ b/osdep-freebsd.c
> > @@ -133,7 +133,7 @@ error:
> >  }
> >  
> >  char *
> > -osdep_get_cwd(int fd)
> > +osdep_get_cwd_fallback(int fd)
> >  {
> >  	static char		 wd[PATH_MAX];
> >  	struct kinfo_file	*info = NULL;
> > @@ -158,6 +158,31 @@ osdep_get_cwd(int fd)
> >  	return (NULL);
> >  }
> >  
> > +#ifdef KERN_PROC_CWD
> > +char *
> > +osdep_get_cwd(int fd)
> > +{
> > +	static struct kinfo_file info;
> > +	int	name[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, 0 };
> > +	size_t	len = sizeof info;
> > +
> > +	if ((name[3] = tcgetpgrp(fd)) == -1)
> > +		return (NULL);
> > +	if (sysctl(name, 4, &info, &len, NULL, 0) == -1) {
> > +		if (errno == ENOENT)
> > +			return (osdep_get_cwd_fallback(fd));
> > +		return (NULL);
> > +	}
> > +	return (info.kf_path);
> 
> 
> tmux calls this quite often and trying out this sysctl just to see it
> fail each time is a waste. have a static var to indicate the failure and
> to know when to fallback immediately.
> 
> Also this probably should be reworked to obtain tcgetpgrp once and then
> decide which sysctl to use, but that's largely a perference matter.
> 

A fallback indicator has been added. New patch:

diff --git a/osdep-freebsd.c b/osdep-freebsd.c
index d596eab..74b5c91 100644
--- a/osdep-freebsd.c
+++ b/osdep-freebsd.c
@@ -25,6 +25,7 @@
 #include <err.h>
 #include <errno.h>
 #include <event.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -132,8 +133,8 @@ error:
 	return (NULL);
 }
 
-char *
-osdep_get_cwd(int fd)
+static char *
+osdep_get_cwd_fallback(int fd)
 {
 	static char		 wd[PATH_MAX];
 	struct kinfo_file	*info = NULL;
@@ -158,6 +159,38 @@ osdep_get_cwd(int fd)
 	return (NULL);
 }
 
+#ifdef KERN_PROC_CWD
+char *
+osdep_get_cwd(int fd)
+{
+	static struct kinfo_file info;
+	static bool fallback = false;
+	int	name[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, 0 };
+	size_t	len = sizeof info;
+
+	if (fallback)
+		return (osdep_get_cwd_fallback(fd));
+
+	if ((name[3] = tcgetpgrp(fd)) == -1)
+		return (NULL);
+
+	if (sysctl(name, 4, &info, &len, NULL, 0) == -1) {
+		if (errno == ENOENT) {
+			fallback = true;
+			return (osdep_get_cwd_fallback(fd));
+		}
+		return (NULL);
+	}
+	return (info.kf_path);
+}
+#else /* !KERN_PROC_CWD */
+char *
+osdep_get_cwd(int fd)
+{
+	return (osdep_get_cwd_fallback(fd));
+}
+#endif /* KERN_PROC_CWD */
+
 struct event_base *
 osdep_event_init(void)
 {
-- 
2.1.0

Tiwei Bie



More information about the freebsd-hackers mailing list