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:          2df923c5d2 ("pwd: Clean up and adopt POSIX semantics")
MFC after:      3 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D59709

(cherry picked from commit 72bb9eb7b6)
This commit is contained in:
Olivier Certner committed 2026-10-08 14:20:00 +02:00
1 parent 8436cbdb90
commit 3d64b7fc93
1 file changed
+14 -7
+14 -7
View File
@@ -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);
}