1*56bb7041Schristos /* Copyright (C) 1991-1999, 2004-2020 Free Software Foundation, Inc.
2*56bb7041Schristos    This file is part of the GNU C Library.
3*56bb7041Schristos 
4*56bb7041Schristos    This program is free software: you can redistribute it and/or modify
5*56bb7041Schristos    it under the terms of the GNU General Public License as published by
6*56bb7041Schristos    the Free Software Foundation; either version 3 of the License, or
7*56bb7041Schristos    (at your option) any later version.
8*56bb7041Schristos 
9*56bb7041Schristos    This program is distributed in the hope that it will be useful,
10*56bb7041Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*56bb7041Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*56bb7041Schristos    GNU General Public License for more details.
13*56bb7041Schristos 
14*56bb7041Schristos    You should have received a copy of the GNU General Public License
15*56bb7041Schristos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16*56bb7041Schristos 
17*56bb7041Schristos #if !_LIBC
18*56bb7041Schristos # include <config.h>
19*56bb7041Schristos # include <unistd.h>
20*56bb7041Schristos #endif
21*56bb7041Schristos 
22*56bb7041Schristos #include <errno.h>
23*56bb7041Schristos #include <sys/types.h>
24*56bb7041Schristos #include <sys/stat.h>
25*56bb7041Schristos #include <stdbool.h>
26*56bb7041Schristos #include <stddef.h>
27*56bb7041Schristos 
28*56bb7041Schristos #include <fcntl.h> /* For AT_FDCWD on Solaris 9.  */
29*56bb7041Schristos 
30*56bb7041Schristos /* If this host provides the openat function or if we're using the
31*56bb7041Schristos    gnulib replacement function with a native fdopendir, then enable
32*56bb7041Schristos    code below to make getcwd more efficient and robust.  */
33*56bb7041Schristos #if defined HAVE_OPENAT || (defined GNULIB_OPENAT && defined HAVE_FDOPENDIR)
34*56bb7041Schristos # define HAVE_OPENAT_SUPPORT 1
35*56bb7041Schristos #else
36*56bb7041Schristos # define HAVE_OPENAT_SUPPORT 0
37*56bb7041Schristos #endif
38*56bb7041Schristos 
39*56bb7041Schristos #ifndef __set_errno
40*56bb7041Schristos # define __set_errno(val) (errno = (val))
41*56bb7041Schristos #endif
42*56bb7041Schristos 
43*56bb7041Schristos #include <dirent.h>
44*56bb7041Schristos #ifndef _D_EXACT_NAMLEN
45*56bb7041Schristos # define _D_EXACT_NAMLEN(d) strlen ((d)->d_name)
46*56bb7041Schristos #endif
47*56bb7041Schristos #ifndef _D_ALLOC_NAMLEN
48*56bb7041Schristos # define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1)
49*56bb7041Schristos #endif
50*56bb7041Schristos 
51*56bb7041Schristos #include <unistd.h>
52*56bb7041Schristos #include <stdlib.h>
53*56bb7041Schristos #include <string.h>
54*56bb7041Schristos 
55*56bb7041Schristos #if _LIBC
56*56bb7041Schristos # ifndef mempcpy
57*56bb7041Schristos #  define mempcpy __mempcpy
58*56bb7041Schristos # endif
59*56bb7041Schristos #endif
60*56bb7041Schristos 
61*56bb7041Schristos #ifndef MAX
62*56bb7041Schristos # define MAX(a, b) ((a) < (b) ? (b) : (a))
63*56bb7041Schristos #endif
64*56bb7041Schristos #ifndef MIN
65*56bb7041Schristos # define MIN(a, b) ((a) < (b) ? (a) : (b))
66*56bb7041Schristos #endif
67*56bb7041Schristos 
68*56bb7041Schristos #include "pathmax.h"
69*56bb7041Schristos 
70*56bb7041Schristos /* In this file, PATH_MAX only serves as a threshold for choosing among two
71*56bb7041Schristos    algorithms.  */
72*56bb7041Schristos #ifndef PATH_MAX
73*56bb7041Schristos # define PATH_MAX 8192
74*56bb7041Schristos #endif
75*56bb7041Schristos 
76*56bb7041Schristos #if D_INO_IN_DIRENT
77*56bb7041Schristos # define MATCHING_INO(dp, ino) ((dp)->d_ino == (ino))
78*56bb7041Schristos #else
79*56bb7041Schristos # define MATCHING_INO(dp, ino) true
80*56bb7041Schristos #endif
81*56bb7041Schristos 
82*56bb7041Schristos #if HAVE_MSVC_INVALID_PARAMETER_HANDLER
83*56bb7041Schristos # include "msvc-inval.h"
84*56bb7041Schristos #endif
85*56bb7041Schristos 
86*56bb7041Schristos #if !_LIBC
87*56bb7041Schristos # define __getcwd rpl_getcwd
88*56bb7041Schristos # define __lstat lstat
89*56bb7041Schristos # define __closedir closedir
90*56bb7041Schristos # define __opendir opendir
91*56bb7041Schristos # define __readdir readdir
92*56bb7041Schristos #endif
93*56bb7041Schristos 
94*56bb7041Schristos /* The results of opendir() in this file are not used with dirfd and fchdir,
95*56bb7041Schristos    and we do not leak fds to any single-threaded code that could use stdio,
96*56bb7041Schristos    therefore save some unnecessary recursion in fchdir.c.
97*56bb7041Schristos    FIXME - if the kernel ever adds support for multi-thread safety for
98*56bb7041Schristos    avoiding standard fds, then we should use opendir_safer and
99*56bb7041Schristos    openat_safer.  */
100*56bb7041Schristos #ifdef GNULIB_defined_opendir
101*56bb7041Schristos # undef opendir
102*56bb7041Schristos #endif
103*56bb7041Schristos #ifdef GNULIB_defined_closedir
104*56bb7041Schristos # undef closedir
105*56bb7041Schristos #endif
106*56bb7041Schristos 
107*56bb7041Schristos #ifdef _MSC_VER
108*56bb7041Schristos # if HAVE_MSVC_INVALID_PARAMETER_HANDLER
109*56bb7041Schristos static char *
getcwd_nothrow(char * buf,size_t size)110*56bb7041Schristos getcwd_nothrow (char *buf, size_t size)
111*56bb7041Schristos {
112*56bb7041Schristos   char *result;
113*56bb7041Schristos 
114*56bb7041Schristos   TRY_MSVC_INVAL
115*56bb7041Schristos     {
116*56bb7041Schristos       result = _getcwd (buf, size);
117*56bb7041Schristos     }
118*56bb7041Schristos   CATCH_MSVC_INVAL
119*56bb7041Schristos     {
120*56bb7041Schristos       result = NULL;
121*56bb7041Schristos       errno = ERANGE;
122*56bb7041Schristos     }
123*56bb7041Schristos   DONE_MSVC_INVAL;
124*56bb7041Schristos 
125*56bb7041Schristos   return result;
126*56bb7041Schristos }
127*56bb7041Schristos # else
128*56bb7041Schristos #  define getcwd_nothrow _getcwd
129*56bb7041Schristos # endif
130*56bb7041Schristos # define getcwd_system getcwd_nothrow
131*56bb7041Schristos #else
132*56bb7041Schristos # define getcwd_system getcwd
133*56bb7041Schristos #endif
134*56bb7041Schristos 
135*56bb7041Schristos /* Get the name of the current working directory, and put it in SIZE
136*56bb7041Schristos    bytes of BUF.  Returns NULL with errno set if the directory couldn't be
137*56bb7041Schristos    determined or SIZE was too small.  If successful, returns BUF.  In GNU,
138*56bb7041Schristos    if BUF is NULL, an array is allocated with 'malloc'; the array is SIZE
139*56bb7041Schristos    bytes long, unless SIZE == 0, in which case it is as big as necessary.  */
140*56bb7041Schristos 
141*56bb7041Schristos char *
__getcwd(char * buf,size_t size)142*56bb7041Schristos __getcwd (char *buf, size_t size)
143*56bb7041Schristos {
144*56bb7041Schristos   /* Lengths of big file name components and entire file names, and a
145*56bb7041Schristos      deep level of file name nesting.  These numbers are not upper
146*56bb7041Schristos      bounds; they are merely large values suitable for initial
147*56bb7041Schristos      allocations, designed to be large enough for most real-world
148*56bb7041Schristos      uses.  */
149*56bb7041Schristos   enum
150*56bb7041Schristos     {
151*56bb7041Schristos       BIG_FILE_NAME_COMPONENT_LENGTH = 255,
152*56bb7041Schristos       BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
153*56bb7041Schristos       DEEP_NESTING = 100
154*56bb7041Schristos     };
155*56bb7041Schristos 
156*56bb7041Schristos #if HAVE_OPENAT_SUPPORT
157*56bb7041Schristos   int fd = AT_FDCWD;
158*56bb7041Schristos   bool fd_needs_closing = false;
159*56bb7041Schristos #else
160*56bb7041Schristos   char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
161*56bb7041Schristos   char *dotlist = dots;
162*56bb7041Schristos   size_t dotsize = sizeof dots;
163*56bb7041Schristos   size_t dotlen = 0;
164*56bb7041Schristos #endif
165*56bb7041Schristos   DIR *dirstream = NULL;
166*56bb7041Schristos   dev_t rootdev, thisdev;
167*56bb7041Schristos   ino_t rootino, thisino;
168*56bb7041Schristos   char *dir;
169*56bb7041Schristos   register char *dirp;
170*56bb7041Schristos   struct stat st;
171*56bb7041Schristos   size_t allocated = size;
172*56bb7041Schristos   size_t used;
173*56bb7041Schristos 
174*56bb7041Schristos #if HAVE_MINIMALLY_WORKING_GETCWD
175*56bb7041Schristos   /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and
176*56bb7041Schristos      this is much slower than the system getcwd (at least on
177*56bb7041Schristos      GNU/Linux).  So trust the system getcwd's results unless they
178*56bb7041Schristos      look suspicious.
179*56bb7041Schristos 
180*56bb7041Schristos      Use the system getcwd even if we have openat support, since the
181*56bb7041Schristos      system getcwd works even when a parent is unreadable, while the
182*56bb7041Schristos      openat-based approach does not.
183*56bb7041Schristos 
184*56bb7041Schristos      But on AIX 5.1..7.1, the system getcwd is not even minimally
185*56bb7041Schristos      working: If the current directory name is slightly longer than
186*56bb7041Schristos      PATH_MAX, it omits the first directory component and returns
187*56bb7041Schristos      this wrong result with errno = 0.  */
188*56bb7041Schristos 
189*56bb7041Schristos # undef getcwd
190*56bb7041Schristos   dir = getcwd_system (buf, size);
191*56bb7041Schristos   if (dir || (size && errno == ERANGE))
192*56bb7041Schristos     return dir;
193*56bb7041Schristos 
194*56bb7041Schristos   /* Solaris getcwd (NULL, 0) fails with errno == EINVAL, but it has
195*56bb7041Schristos      internal magic that lets it work even if an ancestor directory is
196*56bb7041Schristos      inaccessible, which is better in many cases.  So in this case try
197*56bb7041Schristos      again with a buffer that's almost always big enough.  */
198*56bb7041Schristos   if (errno == EINVAL && buf == NULL && size == 0)
199*56bb7041Schristos     {
200*56bb7041Schristos       char big_buffer[BIG_FILE_NAME_LENGTH + 1];
201*56bb7041Schristos       dir = getcwd_system (big_buffer, sizeof big_buffer);
202*56bb7041Schristos       if (dir)
203*56bb7041Schristos         return strdup (dir);
204*56bb7041Schristos     }
205*56bb7041Schristos 
206*56bb7041Schristos # if HAVE_PARTLY_WORKING_GETCWD
207*56bb7041Schristos   /* The system getcwd works, except it sometimes fails when it
208*56bb7041Schristos      shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.    */
209*56bb7041Schristos   if (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT)
210*56bb7041Schristos     return NULL;
211*56bb7041Schristos # endif
212*56bb7041Schristos #endif
213*56bb7041Schristos 
214*56bb7041Schristos   if (size == 0)
215*56bb7041Schristos     {
216*56bb7041Schristos       if (buf != NULL)
217*56bb7041Schristos         {
218*56bb7041Schristos           __set_errno (EINVAL);
219*56bb7041Schristos           return NULL;
220*56bb7041Schristos         }
221*56bb7041Schristos 
222*56bb7041Schristos       allocated = BIG_FILE_NAME_LENGTH + 1;
223*56bb7041Schristos     }
224*56bb7041Schristos 
225*56bb7041Schristos   if (buf == NULL)
226*56bb7041Schristos     {
227*56bb7041Schristos       dir = malloc (allocated);
228*56bb7041Schristos       if (dir == NULL)
229*56bb7041Schristos         return NULL;
230*56bb7041Schristos     }
231*56bb7041Schristos   else
232*56bb7041Schristos     dir = buf;
233*56bb7041Schristos 
234*56bb7041Schristos   dirp = dir + allocated;
235*56bb7041Schristos   *--dirp = '\0';
236*56bb7041Schristos 
237*56bb7041Schristos   if (__lstat (".", &st) < 0)
238*56bb7041Schristos     goto lose;
239*56bb7041Schristos   thisdev = st.st_dev;
240*56bb7041Schristos   thisino = st.st_ino;
241*56bb7041Schristos 
242*56bb7041Schristos   if (__lstat ("/", &st) < 0)
243*56bb7041Schristos     goto lose;
244*56bb7041Schristos   rootdev = st.st_dev;
245*56bb7041Schristos   rootino = st.st_ino;
246*56bb7041Schristos 
247*56bb7041Schristos   while (!(thisdev == rootdev && thisino == rootino))
248*56bb7041Schristos     {
249*56bb7041Schristos       struct dirent *d;
250*56bb7041Schristos       dev_t dotdev;
251*56bb7041Schristos       ino_t dotino;
252*56bb7041Schristos       bool mount_point;
253*56bb7041Schristos       int parent_status;
254*56bb7041Schristos       size_t dirroom;
255*56bb7041Schristos       size_t namlen;
256*56bb7041Schristos       bool use_d_ino = true;
257*56bb7041Schristos 
258*56bb7041Schristos       /* Look at the parent directory.  */
259*56bb7041Schristos #if HAVE_OPENAT_SUPPORT
260*56bb7041Schristos       fd = openat (fd, "..", O_RDONLY);
261*56bb7041Schristos       if (fd < 0)
262*56bb7041Schristos         goto lose;
263*56bb7041Schristos       fd_needs_closing = true;
264*56bb7041Schristos       parent_status = fstat (fd, &st);
265*56bb7041Schristos #else
266*56bb7041Schristos       dotlist[dotlen++] = '.';
267*56bb7041Schristos       dotlist[dotlen++] = '.';
268*56bb7041Schristos       dotlist[dotlen] = '\0';
269*56bb7041Schristos       parent_status = __lstat (dotlist, &st);
270*56bb7041Schristos #endif
271*56bb7041Schristos       if (parent_status != 0)
272*56bb7041Schristos         goto lose;
273*56bb7041Schristos 
274*56bb7041Schristos       if (dirstream && __closedir (dirstream) != 0)
275*56bb7041Schristos         {
276*56bb7041Schristos           dirstream = NULL;
277*56bb7041Schristos           goto lose;
278*56bb7041Schristos         }
279*56bb7041Schristos 
280*56bb7041Schristos       /* Figure out if this directory is a mount point.  */
281*56bb7041Schristos       dotdev = st.st_dev;
282*56bb7041Schristos       dotino = st.st_ino;
283*56bb7041Schristos       mount_point = dotdev != thisdev;
284*56bb7041Schristos 
285*56bb7041Schristos       /* Search for the last directory.  */
286*56bb7041Schristos #if HAVE_OPENAT_SUPPORT
287*56bb7041Schristos       dirstream = fdopendir (fd);
288*56bb7041Schristos       if (dirstream == NULL)
289*56bb7041Schristos         goto lose;
290*56bb7041Schristos       fd_needs_closing = false;
291*56bb7041Schristos #else
292*56bb7041Schristos       dirstream = __opendir (dotlist);
293*56bb7041Schristos       if (dirstream == NULL)
294*56bb7041Schristos         goto lose;
295*56bb7041Schristos       dotlist[dotlen++] = '/';
296*56bb7041Schristos #endif
297*56bb7041Schristos       for (;;)
298*56bb7041Schristos         {
299*56bb7041Schristos           /* Clear errno to distinguish EOF from error if readdir returns
300*56bb7041Schristos              NULL.  */
301*56bb7041Schristos           __set_errno (0);
302*56bb7041Schristos           d = __readdir (dirstream);
303*56bb7041Schristos 
304*56bb7041Schristos           /* When we've iterated through all directory entries without finding
305*56bb7041Schristos              one with a matching d_ino, rewind the stream and consider each
306*56bb7041Schristos              name again, but this time, using lstat.  This is necessary in a
307*56bb7041Schristos              chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
308*56bb7041Schristos              .., ../.., ../../.., etc. all had the same device number, yet the
309*56bb7041Schristos              d_ino values for entries in / did not match those obtained
310*56bb7041Schristos              via lstat.  */
311*56bb7041Schristos           if (d == NULL && errno == 0 && use_d_ino)
312*56bb7041Schristos             {
313*56bb7041Schristos               use_d_ino = false;
314*56bb7041Schristos               rewinddir (dirstream);
315*56bb7041Schristos               d = __readdir (dirstream);
316*56bb7041Schristos             }
317*56bb7041Schristos 
318*56bb7041Schristos           if (d == NULL)
319*56bb7041Schristos             {
320*56bb7041Schristos               if (errno == 0)
321*56bb7041Schristos                 /* EOF on dirstream, which can mean e.g., that the current
322*56bb7041Schristos                    directory has been removed.  */
323*56bb7041Schristos                 __set_errno (ENOENT);
324*56bb7041Schristos               goto lose;
325*56bb7041Schristos             }
326*56bb7041Schristos           if (d->d_name[0] == '.' &&
327*56bb7041Schristos               (d->d_name[1] == '\0' ||
328*56bb7041Schristos                (d->d_name[1] == '.' && d->d_name[2] == '\0')))
329*56bb7041Schristos             continue;
330*56bb7041Schristos 
331*56bb7041Schristos           if (use_d_ino)
332*56bb7041Schristos             {
333*56bb7041Schristos               bool match = (MATCHING_INO (d, thisino) || mount_point);
334*56bb7041Schristos               if (! match)
335*56bb7041Schristos                 continue;
336*56bb7041Schristos             }
337*56bb7041Schristos 
338*56bb7041Schristos           {
339*56bb7041Schristos             int entry_status;
340*56bb7041Schristos #if HAVE_OPENAT_SUPPORT
341*56bb7041Schristos             entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
342*56bb7041Schristos #else
343*56bb7041Schristos             /* Compute size needed for this file name, or for the file
344*56bb7041Schristos                name ".." in the same directory, whichever is larger.
345*56bb7041Schristos                Room for ".." might be needed the next time through
346*56bb7041Schristos                the outer loop.  */
347*56bb7041Schristos             size_t name_alloc = _D_ALLOC_NAMLEN (d);
348*56bb7041Schristos             size_t filesize = dotlen + MAX (sizeof "..", name_alloc);
349*56bb7041Schristos 
350*56bb7041Schristos             if (filesize < dotlen)
351*56bb7041Schristos               goto memory_exhausted;
352*56bb7041Schristos 
353*56bb7041Schristos             if (dotsize < filesize)
354*56bb7041Schristos               {
355*56bb7041Schristos                 /* My, what a deep directory tree you have, Grandma.  */
356*56bb7041Schristos                 size_t newsize = MAX (filesize, dotsize * 2);
357*56bb7041Schristos                 size_t i;
358*56bb7041Schristos                 if (newsize < dotsize)
359*56bb7041Schristos                   goto memory_exhausted;
360*56bb7041Schristos                 if (dotlist != dots)
361*56bb7041Schristos                   free (dotlist);
362*56bb7041Schristos                 dotlist = malloc (newsize);
363*56bb7041Schristos                 if (dotlist == NULL)
364*56bb7041Schristos                   goto lose;
365*56bb7041Schristos                 dotsize = newsize;
366*56bb7041Schristos 
367*56bb7041Schristos                 i = 0;
368*56bb7041Schristos                 do
369*56bb7041Schristos                   {
370*56bb7041Schristos                     dotlist[i++] = '.';
371*56bb7041Schristos                     dotlist[i++] = '.';
372*56bb7041Schristos                     dotlist[i++] = '/';
373*56bb7041Schristos                   }
374*56bb7041Schristos                 while (i < dotlen);
375*56bb7041Schristos               }
376*56bb7041Schristos 
377*56bb7041Schristos             memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
378*56bb7041Schristos             entry_status = __lstat (dotlist, &st);
379*56bb7041Schristos #endif
380*56bb7041Schristos             /* We don't fail here if we cannot stat() a directory entry.
381*56bb7041Schristos                This can happen when (network) file systems fail.  If this
382*56bb7041Schristos                entry is in fact the one we are looking for we will find
383*56bb7041Schristos                out soon as we reach the end of the directory without
384*56bb7041Schristos                having found anything.  */
385*56bb7041Schristos             if (entry_status == 0 && S_ISDIR (st.st_mode)
386*56bb7041Schristos                 && st.st_dev == thisdev && st.st_ino == thisino)
387*56bb7041Schristos               break;
388*56bb7041Schristos           }
389*56bb7041Schristos         }
390*56bb7041Schristos 
391*56bb7041Schristos       dirroom = dirp - dir;
392*56bb7041Schristos       namlen = _D_EXACT_NAMLEN (d);
393*56bb7041Schristos 
394*56bb7041Schristos       if (dirroom <= namlen)
395*56bb7041Schristos         {
396*56bb7041Schristos           if (size != 0)
397*56bb7041Schristos             {
398*56bb7041Schristos               __set_errno (ERANGE);
399*56bb7041Schristos               goto lose;
400*56bb7041Schristos             }
401*56bb7041Schristos           else
402*56bb7041Schristos             {
403*56bb7041Schristos               char *tmp;
404*56bb7041Schristos               size_t oldsize = allocated;
405*56bb7041Schristos 
406*56bb7041Schristos               allocated += MAX (allocated, namlen);
407*56bb7041Schristos               if (allocated < oldsize
408*56bb7041Schristos                   || ! (tmp = realloc (dir, allocated)))
409*56bb7041Schristos                 goto memory_exhausted;
410*56bb7041Schristos 
411*56bb7041Schristos               /* Move current contents up to the end of the buffer.
412*56bb7041Schristos                  This is guaranteed to be non-overlapping.  */
413*56bb7041Schristos               dirp = memcpy (tmp + allocated - (oldsize - dirroom),
414*56bb7041Schristos                              tmp + dirroom,
415*56bb7041Schristos                              oldsize - dirroom);
416*56bb7041Schristos               dir = tmp;
417*56bb7041Schristos             }
418*56bb7041Schristos         }
419*56bb7041Schristos       dirp -= namlen;
420*56bb7041Schristos       memcpy (dirp, d->d_name, namlen);
421*56bb7041Schristos       *--dirp = '/';
422*56bb7041Schristos 
423*56bb7041Schristos       thisdev = dotdev;
424*56bb7041Schristos       thisino = dotino;
425*56bb7041Schristos     }
426*56bb7041Schristos 
427*56bb7041Schristos   if (dirstream && __closedir (dirstream) != 0)
428*56bb7041Schristos     {
429*56bb7041Schristos       dirstream = NULL;
430*56bb7041Schristos       goto lose;
431*56bb7041Schristos     }
432*56bb7041Schristos 
433*56bb7041Schristos   if (dirp == &dir[allocated - 1])
434*56bb7041Schristos     *--dirp = '/';
435*56bb7041Schristos 
436*56bb7041Schristos #if ! HAVE_OPENAT_SUPPORT
437*56bb7041Schristos   if (dotlist != dots)
438*56bb7041Schristos     free (dotlist);
439*56bb7041Schristos #endif
440*56bb7041Schristos 
441*56bb7041Schristos   used = dir + allocated - dirp;
442*56bb7041Schristos   memmove (dir, dirp, used);
443*56bb7041Schristos 
444*56bb7041Schristos   if (size == 0)
445*56bb7041Schristos     /* Ensure that the buffer is only as large as necessary.  */
446*56bb7041Schristos     buf = (used < allocated ? realloc (dir, used) : dir);
447*56bb7041Schristos 
448*56bb7041Schristos   if (buf == NULL)
449*56bb7041Schristos     /* Either buf was NULL all along, or 'realloc' failed but
450*56bb7041Schristos        we still have the original string.  */
451*56bb7041Schristos     buf = dir;
452*56bb7041Schristos 
453*56bb7041Schristos   return buf;
454*56bb7041Schristos 
455*56bb7041Schristos  memory_exhausted:
456*56bb7041Schristos   __set_errno (ENOMEM);
457*56bb7041Schristos  lose:
458*56bb7041Schristos   {
459*56bb7041Schristos     int save = errno;
460*56bb7041Schristos     if (dirstream)
461*56bb7041Schristos       __closedir (dirstream);
462*56bb7041Schristos #if HAVE_OPENAT_SUPPORT
463*56bb7041Schristos     if (fd_needs_closing)
464*56bb7041Schristos       close (fd);
465*56bb7041Schristos #else
466*56bb7041Schristos     if (dotlist != dots)
467*56bb7041Schristos       free (dotlist);
468*56bb7041Schristos #endif
469*56bb7041Schristos     if (buf == NULL)
470*56bb7041Schristos       free (dir);
471*56bb7041Schristos     __set_errno (save);
472*56bb7041Schristos   }
473*56bb7041Schristos   return NULL;
474*56bb7041Schristos }
475*56bb7041Schristos 
476*56bb7041Schristos #ifdef weak_alias
477*56bb7041Schristos weak_alias (__getcwd, getcwd)
478*56bb7041Schristos #endif
479