summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2021-02-27 00:47:49 +0000
committerAndy Fiddaman <omnios@citrus-it.co.uk>2021-03-16 19:20:11 +0000
commitaa15372140b6b509a26742fd85fe78dd77d9a642 (patch)
treeb9e91382bfdd60d331dc3d03d0570212a4339854
parentf38f28fdbc29b3c5020295a6c6cb1ac52e949978 (diff)
downloadillumos-joyent-aa15372140b6b509a26742fd85fe78dd77d9a642.tar.gz
13586 getcwd() should accept a 0 length argument
Reviewed by: Jason King <jason.king@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Reviewed by: Gordon Ross <gordon.w.ross@gmail.com> Reviewed by: Robert Mustacchi <rm@fingolfin.org> Approved by: Rich Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/lib/libc/port/gen/getcwd.c50
-rw-r--r--usr/src/man/man3c/getcwd.3c309
2 files changed, 202 insertions, 157 deletions
diff --git a/usr/src/lib/libc/port/gen/getcwd.c b/usr/src/lib/libc/port/gen/getcwd.c
index d832d798d7..62f12e027e 100644
--- a/usr/src/lib/libc/port/gen/getcwd.c
+++ b/usr/src/lib/libc/port/gen/getcwd.c
@@ -22,10 +22,9 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* getcwd() returns the pathname of the current working directory.
* On error, a NULL pointer is returned and errno is set.
@@ -34,16 +33,63 @@
#pragma weak _getcwd = getcwd
#include "lint.h"
+#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <errno.h>
+#include <limits.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
char *
getcwd(char *pathname, size_t size)
{
int alloc = 0;
+ if (size == 0 && pathname == NULL) {
+ /*
+ * If no size was provided, start with a buffer that should
+ * accommodate any normal path and, if it is not big enough,
+ * keep doubling it to try and make enough space.
+ *
+ * Any non-global zone path is longer when observed from the
+ * global zone, and some filesystems, including ZFS, support
+ * paths much longer than MAXPATHLEN/_PC_PATH_MAX.
+ *
+ * To protect against unbounded memory usage, cap to 128KiB.
+ * This is an arbitrary limit which is far bigger than the
+ * length of any practical path on the system.
+ */
+ if ((size = pathconf(".", _PC_PATH_MAX)) == -1)
+ size = MAXPATHLEN;
+
+ while (size <= 0x20000) {
+ if ((pathname = reallocf(pathname, size)) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (syscall(SYS_getcwd, pathname, size) == 0) {
+ char *ret;
+
+ /*
+ * Shrink the buffer to the length actually
+ * required to hold the final path.
+ */
+ ret = realloc(pathname, strlen(pathname) + 1);
+ if (ret == NULL)
+ return (pathname);
+
+ return (ret);
+ }
+ if (errno != ERANGE)
+ break;
+ size <<= 1;
+ }
+ free(pathname);
+ return (NULL);
+ }
+
if (size == 0) {
errno = EINVAL;
return (NULL);
diff --git a/usr/src/man/man3c/getcwd.3c b/usr/src/man/man3c/getcwd.3c
index f1114bc6dd..045bfafa67 100644
--- a/usr/src/man/man3c/getcwd.3c
+++ b/usr/src/man/man3c/getcwd.3c
@@ -43,110 +43,126 @@
.\" Copyright 1989 AT&T
.\" Copyright (c) 2001, The IEEE and The Open Group. All Rights Reserved.
.\" Portions Copyright (c) 2004, Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
.\"
-.TH GETCWD 3C "Oct 18, 2004"
-.SH NAME
-getcwd \- get pathname of current working directory
-.SH SYNOPSIS
-.LP
-.nf
-#include <unistd.h>
-
-\fBchar *\fR\fBgetcwd\fR(\fBchar *\fR\fIbuf\fR, \fBsize_t\fR \fIsize\fR);
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-The \fBgetcwd()\fR function places an absolute pathname of the current working
-directory in the array pointed to by \fIbuf\fR, and returns \fIbuf\fR. The
-pathname copied to the array contains no components that are symbolic links.
-The \fIsize\fR argument is the size in bytes of the character array pointed to
-by \fIbuf\fR and must be at least one greater than the length of the pathname
-to be returned.
-.sp
-.LP
-If \fIbuf\fR is not a null pointer, the pathname is stored in the space pointed
-to by \fIbuf\fR.
-.sp
-.LP
-If \fIbuf\fR is a null pointer, \fBgetcwd()\fR obtains \fIsize\fR bytes of
-space using \fBmalloc\fR(3C). The pointer returned by \fBgetcwd()\fR can be
-used as the argument in a subsequent call to \fBfree()\fR.
-.SH RETURN VALUES
-.sp
-.LP
-Upon successful completion, \fBgetcwd()\fR returns the \fIbuf\fR argument. If
-\fIbuf\fR is an invalid destination buffer address, \fINULL\fR is returned and
-\fBerrno\fR is set to \fBEFAULT\fR. Otherwise, a null pointer is returned and
-\fBerrno\fR is set to indicate the error.
-.SH ERRORS
-.sp
-.LP
-The \fBgetcwd()\fR function will fail if:
-.sp
-.ne 2
-.na
-\fB\fBEFAULT\fR\fR
-.ad
-.RS 10n
-The \fIbuf\fR argument is an invalid destination buffer address.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBEINVAL\fR\fR
-.ad
-.RS 10n
-The \fIsize\fR argument is equal to 0.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBERANGE\fR\fR
-.ad
-.RS 10n
-The \fIsize\fR argument is greater than 0 and less than the length of the
-pathname plus 1.
-.RE
-
-.sp
-.LP
-The \fBgetcwd()\fR function may fail if:
-.sp
-.ne 2
-.na
-\fB\fBEACCES\fR\fR
-.ad
-.RS 10n
+.Dd February 27, 2021
+.Dt GETCWD 3C
+.Os
+.Sh NAME
+.Nm getcwd
+.Nd get pathname of current working directory
+.Sh SYNOPSIS
+.In unistd.h
+.Ft "char *"
+.Fo getcwd
+.Fa "char *buf"
+.Fa "size_t size"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn getcwd
+function returns a pointer to a buffer containing the absolute pathname of the
+current working directory.
+The returned pathname contains no components that are symbolic links.
+.Pp
+When
+.Fa buf
+is not
+.Dv NULL ,
+the absolute pathname will be written into
+.Fa buf
+and
+.Fa size
+represents the length in bytes of
+.Fa buf .
+If the length of the pathname and nul terminator exceeds
+.Fa size ,
+nothing will be written and
+.Fn getcwd
+will return
+.Dv NULL .
+Otherwise,
+.Fn getcwd
+returns
+.Fa buf .
+.Pp
+When
+.Fa buf
+is
+.Dv NULL
+then
+.Fn getcwd
+will allocate memory in which to store the pathname of the current working
+directory.
+If
+.Fa size
+is non-zero, then
+.Fa size
+bytes will be allocated.
+If the length of the pathname and nul terminator exceeds
+.Fa size ,
+the memory will be freed and
+.Fn getcwd
+will return
+.Dv NULL .
+If
+.Fa size
+is zero, then
+.Fn getcwd
+will attempt to allocate enough space to hold the pathname.
+In both cases, it is the caller's responsibility to free the returned buffer
+with the
+.Xr free 3C
+function.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn getcwd
+function returns a pointer to a buffer containing the pathname.
+Otherwise,
+.Dv NULL
+is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn getcwd
+function will fail if:
+.Bl -tag -width Er
+.It Er EFAULT
+The
+.Fa buf
+argument points to an invalid address.
+.It Er EINVAL
+The
+.Fa buf
+argument is not
+.Dv NULL
+and the
+.Fa size
+argument is 0.
+.It Er ERANGE
+The pathname
+.Pq including its terminating nul character
+is too long to fit into the provided
+.Pq or allocated
+buffer.
+.It Er EACCESS
A parent directory cannot be read to get its name.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fBENOMEM\fR\fR
-.ad
-.RS 10n
+.It Er ENOMEM
Insufficient storage space is available.
-.RE
-
-.SH EXAMPLES
-.LP
-\fBExample 1 \fRDetermine the absolute pathname of the current working
-directory.
-.sp
-.LP
+.El
+.Sh EXAMPLES
+.Sy Example 1
+Determine the absolute pathname of the current working directory.
+.Pp
The following example returns a pointer to an array that holds the absolute
-pathname of the current working directory. The pointer is returned in the
-\fIptr\fR variable, which points to the \fIbuf\fR array where the pathname is
-stored.
-
-.sp
-.in +2
-.nf
+pathname of the current working directory.
+The pointer is returned in the
+.Va ptr
+variable, which points to the
+.Va buf
+array where the pathname is stored.
+.Bd -literal -offset Ds
#include <stdlib.h>
#include <unistd.h>
\&...
@@ -155,64 +171,47 @@ char *buf;
char *ptr;
size = pathconf(".", _PC_PATH_MAX);
if ((buf = (char *)malloc((size_t)size)) != NULL)
- ptr = getcwd(buf, (size_t)size);
+ ptr = getcwd(buf, (size_t)size);
\&...
-.fi
-.in -2
-
-.LP
-\fBExample 2 \fRPrint the current working directory.
-.sp
-.LP
+.Ed
+.Pp
+.Sy Example 2
+Print the current working directory.
+.Pp
The following example prints the current working directory.
-
-.sp
-.in +2
-.nf
-#include <unistd.h>
+.Bd -literal -offset Ds
#include <stdio.h>
+#include <unistd.h>
-main(\|)
+int
+main(void)
{
- char *cwd;
- if ((cwd = getcwd(NULL, 64)) == NULL) {
- perror("pwd");
- exit(2);
- }
- (void)printf("%s\en", cwd);
- free(cwd); /* free memory allocated by getcwd() */
- return(0);
-}
-.fi
-.in -2
-
-.SH USAGE
-.sp
-.LP
-Applications should exercise care when using \fBchdir\fR(2) in conjunction with
-\fBgetcwd()\fR. The current working directory is global to all threads within a
-process. If more than one thread calls \fBchdir()\fR to change the working
-directory, a subsequent call to \fBgetcwd()\fR could produce unexpected
-results.
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
+ char *cwd;
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE ATTRIBUTE VALUE
-_
-Interface Stability Standard
-_
-MT-Level MT-Safe
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBchdir\fR(2), \fBmalloc\fR(3C), \fBattributes\fR(5), \fBstandards\fR(5)
+ if ((cwd = getcwd(NULL, 0)) == NULL) {
+ perror("pwd");
+ exit(2);
+ }
+ (void)printf("%s\en", cwd);
+ free(cwd); /* free memory allocated by getcwd() */
+ return(0);
+}
+.Ed
+.Sh USAGE
+Applications should exercise care when using
+.Xr chdir 2
+in conjunction with
+.Fn getcwd .
+The current working directory is global to all threads within a process.
+If more than one thread calls
+.Xr chdir 2
+to change the working directory, a subsequent call to
+.Fn getcwd
+could produce unexpected results.
+.Sh INTERFACE STABILITY
+.Sy Committed
+.Sh SEE ALSO
+.Xr chdir 2 ,
+.Xr free 3C ,
+.Xr attributes 5 ,
+.Xr standards 5