]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/unix/sysv/linux/getcwd.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / getcwd.c
CommitLineData
fe0ec73e 1/* Determine current working directory. Linux version.
2b778ceb 2 Copyright (C) 1997-2021 Free Software Foundation, Inc.
fe0ec73e
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
fe0ec73e
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
fe0ec73e 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6 17 License along with the GNU C Library; if not, see
5a82c748 18 <https://www.gnu.org/licenses/>. */
fe0ec73e 19
958f238f 20#include <assert.h>
fe0ec73e
UD
21#include <errno.h>
22#include <limits.h>
23#include <stdlib.h>
24#include <unistd.h>
df6a4a4a 25#include <sys/param.h>
0dee6738
UD
26
27#include <sysdep.h>
63bda0c1 28#include <sys/syscall.h>
fe0ec73e 29
958f238f 30
8d04a97c
UD
31/* If we compile the file for use in ld.so we don't need the feature
32 that getcwd() allocates the buffers itself. */
a3848485 33#if IS_IN (rtld)
8d04a97c
UD
34# define NO_ALLOCATION 1
35#endif
36
37
7fb90fb8
UD
38/* The "proc" filesystem provides an easy method to retrieve the value.
39 For each process, the corresponding directory contains a symbolic link
40 named `cwd'. Reading the content of this link immediate gives us the
41 information. But we have to take care for systems which do not have
42 the proc filesystem mounted. Use the POSIX implementation in this case. */
fcdbd910
AZ
43
44/* Get the code for the generic version. */
45#define GETCWD_RETURN_TYPE static char *
46#include <sysdeps/posix/getcwd.c>
7fb90fb8 47
fe0ec73e
UD
48char *
49__getcwd (char *buf, size_t size)
50{
fe0ec73e 51 char *path;
fe0ec73e 52 char *result;
6973fc01 53
8d04a97c
UD
54#ifndef NO_ALLOCATION
55 size_t alloc_size = size;
a2b3aa73 56 if (size == 0)
fe0ec73e
UD
57 {
58 if (buf != NULL)
59 {
60 __set_errno (EINVAL);
61 return NULL;
62 }
63
6c7a5753 64 alloc_size = MAX (PATH_MAX, __getpagesize ());
fe0ec73e
UD
65 }
66
8d04a97c 67 if (buf == NULL)
fe0ec73e 68 {
6973fc01 69 path = malloc (alloc_size);
fe0ec73e
UD
70 if (path == NULL)
71 return NULL;
72 }
8d04a97c
UD
73 else
74#else
75# define alloc_size size
76#endif
77 path = buf;
fe0ec73e 78
ffb7875d 79 int retval;
7fb90fb8 80
6277fdab 81 retval = INLINE_SYSCALL (getcwd, 2, path, alloc_size);
52a713fd 82 if (retval > 0 && path[0] == '/')
ffb7875d
JM
83 {
84#ifndef NO_ALLOCATION
85 if (buf == NULL && size == 0)
86 /* Ensure that the buffer is only as large as necessary. */
87 buf = realloc (path, (size_t) retval);
958f238f
UD
88
89 if (buf == NULL)
ffb7875d
JM
90 /* Either buf was NULL all along, or `realloc' failed but
91 we still have the original string. */
92 buf = path;
93#endif
958f238f 94
ffb7875d 95 return buf;
63bda0c1 96 }
63bda0c1 97
52a713fd
DL
98 /* The system call either cannot handle paths longer than a page
99 or can succeed without returning an absolute path. Just use the
ffb7875d 100 generic implementation right away. */
52a713fd 101 if (retval >= 0 || errno == ENAMETOOLONG)
fe0ec73e 102 {
8d04a97c 103#ifndef NO_ALLOCATION
ffb7875d
JM
104 if (buf == NULL && size == 0)
105 {
106 free (path);
107 path = NULL;
fe0ec73e 108 }
958f238f 109#endif
fe0ec73e 110
fcdbd910 111 result = __getcwd_generic (path, size);
6973fc01 112
8d04a97c 113#ifndef NO_ALLOCATION
ffb7875d
JM
114 if (result == NULL && buf == NULL && size != 0)
115 free (path);
8d04a97c 116#endif
6973fc01 117
ffb7875d
JM
118 return result;
119 }
120
121 /* It should never happen that the `getcwd' syscall failed because
122 the buffer is too small if we allocated the buffer ourselves
123 large enough. */
124 assert (errno != ERANGE || buf != NULL || size != 0);
fe0ec73e 125
8d04a97c 126#ifndef NO_ALLOCATION
ffb7875d 127 if (buf == NULL)
fe0ec73e 128 free (path);
8d04a97c 129#endif
fe0ec73e 130
ffb7875d 131 return NULL;
fe0ec73e 132}
db25266c 133libc_hidden_def (__getcwd)
fe0ec73e 134weak_alias (__getcwd, getcwd)