Date: Sun, 2 Feb 2003 18:37:38 +0100 From: Johan Karlsson <johan@freebsd.org> To: audit@freebsd.org, Sheldon Hearn <sheldonh@starjuice.net> Subject: realpath(3) improvement Message-ID: <20030202173738.GA759@numeri.campus.luth.se>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hi
I intend to commit the attached patch to realpath(3) unless
there are objections.
Currently realpath(3) return an error if current directory
is unreadable.
k@numeri ~/realpathtes >ll
total 8
drwxr-xr-x 3 k staff 512 Feb 2 17:52 ./
drwxr-xr-x 55 k staff 3584 Feb 2 17:44 ../
d-wx--x--x 3 k staff 512 Feb 2 16:29 realpathtest/
k@numeri ~/realpathtes >cd realpathtest/
k@numeri ~/realpathtes/realpathtest >/bin/realpath home
realpath: .: Permission denied
k@numeri ~/realpathtes/realpathtest >
With the attached patch one get
k@numeri ~/realpathtes/realpathtest >/home/builds/home/k/FreeBSD-src/current/src/bin/realpath/realpath /home
/home
k@numeri ~/realpathtes/realpathtest >
The problem is in libc not in bin/realpath.
The patch to correct this is from PR 12244.
The attached patch also changes realpath(3) to use strlcpy instead
of strncpy (submitted by imp@). Accordning to strncpy(3) it is
preferable to use strlcpy when portablility isn't an issue.
I would like to know if this is ok to commit as well.
Please have a look at the attached patch and let me know if
you find any problems with it.
Take care
/Johan K
--
Johan Karlsson mailto:johan@FreeBSD.org
[-- Attachment #2 --]
Index: lib/libc/stdlib/realpath.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/realpath.c,v
retrieving revision 1.12
diff -u -r1.12 realpath.c
--- lib/libc/stdlib/realpath.c 15 Jan 2003 21:22:55 -0000 1.12
+++ lib/libc/stdlib/realpath.c 2 Feb 2003 17:01:49 -0000
@@ -65,13 +65,19 @@
{
struct stat sb;
int fd, n, rootd, serrno;
- char *p, *q, wbuf[PATH_MAX];
+ char *p, *q, scwd[PATH_MAX], wbuf[PATH_MAX];
int symlinks = 0;
- /* Save the starting point. */
+ /*
+ * Save the starting point:
+ * First, try open()/fchdir() method and, if this fails,
+ * then try getcwd()/chdir().
+ */
if ((fd = _open(".", O_RDONLY)) < 0) {
- (void)strcpy(resolved, ".");
- return (NULL);
+ if (getcwd(scwd, PATH_MAX) == 0) {
+ (void)strcpy(resolved, ".");
+ return (NULL);
+ }
}
/*
@@ -82,8 +88,7 @@
* if it is a directory, then change to that directory.
* get the current directory name and append the basename.
*/
- (void)strncpy(resolved, path, PATH_MAX - 1);
- resolved[PATH_MAX - 1] = '\0';
+ (void)strlcpy(resolved, path, PATH_MAX);
loop:
q = strrchr(resolved, '/');
if (q != NULL) {
@@ -98,7 +103,7 @@
q = resolved;
}
if (chdir(q) < 0)
- goto err1;
+ goto err;
} else
p = resolved;
@@ -107,17 +112,17 @@
if (S_ISLNK(sb.st_mode)) {
if (++symlinks > MAXSYMLINKS) {
errno = ELOOP;
- goto err1;
+ goto err;
}
n = readlink(p, resolved, PATH_MAX - 1);
if (n < 0)
- goto err1;
+ goto err;
resolved[n] = '\0';
goto loop;
}
if (S_ISDIR(sb.st_mode)) {
if (chdir(p) < 0)
- goto err1;
+ goto err;
p = "";
}
}
@@ -128,7 +133,7 @@
*/
(void)strcpy(wbuf, p);
if (getcwd(resolved, PATH_MAX) == 0)
- goto err1;
+ goto err;
/*
* Join the two strings together, ensuring that the right thing
@@ -142,26 +147,38 @@
if (*wbuf) {
if (strlen(resolved) + strlen(wbuf) + rootd + 1 > PATH_MAX) {
errno = ENAMETOOLONG;
- goto err1;
+ goto err;
}
if (rootd == 0)
(void)strcat(resolved, "/");
(void)strcat(resolved, wbuf);
}
- /* Go back to where we came from. */
- if (fchdir(fd) < 0) {
- serrno = errno;
- goto err2;
+ /*
+ * Go back to where we came from. If fd < 0, we are using the
+ * getcwd()/chdir() method; else, we are using open()/fchdir().
+ */
+ if (fd < 0) {
+ if (chdir(scwd) < 0)
+ return (NULL);
+ } else if (fchdir(fd) < 0) {
+ serrno = errno;
+ (void)_close(fd);
+ errno = serrno;
+ return (NULL);
}
/* It's okay if the close fails, what's an fd more or less? */
(void)_close(fd);
return (resolved);
-err1: serrno = errno;
- (void)fchdir(fd);
-err2: (void)_close(fd);
+err: serrno = errno;
+ if (fd < 0)
+ (void)chdir(scwd);
+ else {
+ (void)fchdir(fd);
+ (void)_close(fd);
+ }
errno = serrno;
return (NULL);
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030202173738.GA759>
