git: 72bb9eb7b6de - main - pwd(1): De-obfuscate, style(9)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 23 Sep 2026 11:38:01 UTC
The branch main has been updated by olce:
URL: https://cgit.FreeBSD.org/src/commit/?id=72bb9eb7b6decc34f343bdcbf0a8df0c73f9edd4
commit 72bb9eb7b6decc34f343bdcbf0a8df0c73f9edd4
Author: Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-09-07 16:09:54 +0000
Commit: Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-09-23 11:37:45 +0000
pwd(1): De-obfuscate, style(9)
In getcwd_logical(), test for a '.' or '..' component in one of the most
straightforward and intelligible ways possible.
In particular, this removes a superfluous re-test of the the component's
first character being '.' when the first one did not pass and, more
importantly, prevents the second test from relying on a side-effect in
the first.
While here, for better clarity, replace the loop that searches for '/'
with a simple call to strchrnul().
Add high-level comments about what is going on.
While here, test explicitly that pointed 'char' values are not 0 ('\0')
(style(9)).
While here, separate the successive steps of getcwd_logical() with blank
lines.
No functional change (intended).
Discussed with: emaste
Fixes: 2df923c5d2d0 ("pwd: Clean up and adopt POSIX semantics")
MFC after: 3 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59709
---
bin/pwd/pwd.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/bin/pwd/pwd.c b/bin/pwd/pwd.c
index 2bbf5457ec17..f619024fdcff 100644
--- a/bin/pwd/pwd.c
+++ b/bin/pwd/pwd.c
@@ -33,33 +33,40 @@
#include <sys/param.h>
#include <sys/stat.h>
+#include <assert.h>
#include <err.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
static char *
getcwd_logical(void)
{
struct stat log, phy;
- char *pwd, *p, *q;
+ char *pwd, *s, *e;
/* $PWD is set and absolute */
if ((pwd = getenv("PWD")) == NULL || *pwd != '/')
return (NULL);
+
/* $PWD does not contain /./ or /../ */
- for (p = pwd; *p; p = q) {
- for (q = ++p; *q && *q != '/'; q++)
- /* nothing */;
- if ((*p == '.' && q == ++p) ||
- (*p == '.' && q == ++p))
+ e = pwd;
+ do {
+ assert(*e == '/');
+ s = e + 1; /* Beginning of next component (may point to NUL). */
+ /* Search for the component's end. */
+ e = strchrnul(s, '/');
+ if (s[0] == '.' && (s + 1 == e || (s[1] == '.' && s + 2 == e)))
return (NULL);
- }
+ } while (*e != '\0');
+
/* $PWD refers to the current directory */
if (stat(pwd, &log) != 0 || stat(".", &phy) != 0 ||
log.st_dev != phy.st_dev || log.st_ino != phy.st_ino)
return (NULL);
+
return (pwd);
}