Skip site navigation (1)Skip section navigation (2)
Date:      Mon,  3 Nov 2014 12:02:05 +0800
From:      Tiwei Bie <btw@mail.ustc.edu.cn>
To:        mjg@freebsd.org
Cc:        freebsd-hackers@freebsd.org
Subject:   [PATCH] Finish the task 'sysctl reporting current working directory'
Message-ID:  <1414987325-23280-1-git-send-email-btw@mail.ustc.edu.cn>

next in thread | raw e-mail | index | archive | help
Hi, Mateusz!

I have finished the task: sysctl reporting current working directory [1].

The patch for tmux is against tmux-1.9a [2].

#1. Patch for FreeBSD:

diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 11ab4ba..4652cb9 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3409,6 +3409,72 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,
     CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc,
     "Process filedesc entries");
 
+/*
+ * Store a process current working directory information to sbuf.
+ *
+ * Takes a locked proc as argument, and returns with the proc unlocked.
+ */
+int
+kern_proc_cwd_out(struct proc *p,  struct sbuf *sb, ssize_t maxlen)
+{
+	struct filedesc *fdp;
+	struct export_fd_buf *efbuf;
+	int error = 0;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+
+	fdp = fdhold(p);
+	PROC_UNLOCK(p);
+
+	if (fdp == NULL)
+		return (error);
+
+	efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
+	efbuf->fdp = fdp;
+	efbuf->sb = sb;
+	efbuf->remainder = maxlen;
+
+	FILEDESC_SLOCK(fdp);
+	/* working directory */
+	if (fdp->fd_cdir != NULL) {
+		vref(fdp->fd_cdir);
+		export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
+	}
+	FILEDESC_SUNLOCK(fdp);
+	fddrop(fdp);
+	free(efbuf, M_TEMP);
+	return (error);
+}
+
+/*
+ * Get per-process current working directory.
+ */
+static int
+sysctl_kern_proc_cwd(SYSCTL_HANDLER_ARGS)
+{
+	struct sbuf sb;
+	struct proc *p;
+	ssize_t maxlen;
+	int error, error2, *name;
+
+	name = (int *)arg1;
+
+	sbuf_new_for_sysctl(&sb, NULL, sizeof(struct kinfo_file), req);
+	error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+	if (error != 0) {
+		sbuf_delete(&sb);
+		return (error);
+	}
+	maxlen = req->oldptr != NULL ? req->oldlen : -1;
+	error = kern_proc_cwd_out(p, &sb, maxlen);
+	error2 = sbuf_finish(&sb);
+	sbuf_delete(&sb);
+	return (error != 0 ? error : error2);
+}
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_CWD, cwd, CTLFLAG_RD|CTLFLAG_MPSAFE,
+    sysctl_kern_proc_cwd, "Process current working directory");
+
 #ifdef DDB
 /*
  * For the purposes of debugging, generate a human-readable string for the
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index d782375..f3173c2 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -657,6 +657,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
 #define	KERN_PROC_UMASK		39	/* process umask */
 #define	KERN_PROC_OSREL		40	/* osreldate for process binary */
 #define	KERN_PROC_SIGTRAMP	41	/* signal trampoline location */
+#define	KERN_PROC_CWD		42	/* process current working directory */
 
 /*
  * KERN_IPC identifiers
diff --git a/sys/sys/user.h b/sys/sys/user.h
index f0d059e..c3b3bc5 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -530,6 +530,7 @@ struct sbuf;
  */
 
 int	kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen);
+int	kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen);
 int	kern_proc_out(struct proc *p, struct sbuf *sb, int flags);
 int	kern_proc_vmmap_out(struct proc *p, struct sbuf *sb);
 
-- 
2.1.0


#2. Patch for tmux:

diff --git a/osdep-freebsd.c b/osdep-freebsd.c
index d596eab..f2443b7 100644
--- a/osdep-freebsd.c
+++ b/osdep-freebsd.c
@@ -136,26 +136,39 @@ char *
 osdep_get_cwd(int fd)
 {
 	static char		 wd[PATH_MAX];
-	struct kinfo_file	*info = NULL;
 	pid_t			 pgrp;
-	int			 nrecords, i;
+	int			 mib[4];
+	size_t			 len;
+	struct kinfo_file	*info;
+	char                    *buf;
+	int                      error;
 
 	if ((pgrp = tcgetpgrp(fd)) == -1)
 		return (NULL);
 
-	if ((info = kinfo_getfile(pgrp, &nrecords)) == NULL)
+	mib[0] = CTL_KERN;
+	mib[1] = KERN_PROC;
+	mib[2] = KERN_PROC_CWD;
+	mib[3] = pgrp;
+
+	error = sysctl(mib, 4, NULL, &len, NULL, 0);
+	if (error)
 		return (NULL);
 
-	for (i = 0; i < nrecords; i++) {
-		if (info[i].kf_fd == KF_FD_TYPE_CWD) {
-			strlcpy(wd, info[i].kf_path, sizeof wd);
-			free(info);
-			return (wd);
-		}
+	buf = malloc(len);
+	if (buf == NULL)
+		return (NULL);
+	error = sysctl(mib, 4, buf, &len, NULL, 0);
+	if (error) {
+		free(buf);
+		return (NULL);
 	}
 
-	free(info);
-	return (NULL);
+	info = (struct kinfo_file *)buf;
+	strlcpy(wd, info->kf_path, sizeof wd);
+
+	free(buf);
+	return (wd);
 }
 
 struct event_base *
-- 
2.1.0

[1] https://wiki.freebsd.org/JuniorJobs#sysctl_reporting_current_working_directory
[2] http://cznic.dl.sourceforge.net/project/tmux/tmux/tmux-1.9/tmux-1.9a.tar.gz

Tiwei Bie




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1414987325-23280-1-git-send-email-btw>