annotate lib/getcwd-lgpl.c @ 14641:9a3f3761a941

getcwd: fix mingw bugs On mingw, getcwd(NULL,1) succeeds, even though glibc documents that with a non-zero size, the allocation will not exceed that many bytes. On mingw, getcwd has the wrong signature. However, we don't have to check for this if anything else triggers the replacement. Also, fix a type bug that crept into the original getcwd-lgpl commit. * m4/getcwd.m4 (gl_FUNC_GETCWD_NULL): Detect one mingw bug. * doc/posix-functions/getcwd.texi (getcwd): Document the problems. * lib/getcwd-lgpl.c (rpl_getcwd): Fix return type. Signed-off-by: Eric Blake <eblake@redhat.com>
author Eric Blake <eblake@redhat.com>
date Wed, 27 Apr 2011 20:40:21 -0600
parents 7a493fbc787a
children a57aca916cfd
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
14629
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
1 /* Copyright (C) 2011 Free Software Foundation, Inc.
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
2 This file is part of gnulib.
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
3
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
4 This program is free software: you can redistribute it and/or modify
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
6 the Free Software Foundation; either version 3 of the License, or
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
7 (at your option) any later version.
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
8
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
12 GNU General Public License for more details.
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
13
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
16
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
17 #include <config.h>
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
18
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
19 /* Specification */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
20 #include <unistd.h>
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
21
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
22 #include <errno.h>
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
23 #include <string.h>
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
24
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
25 #if GNULIB_GETCWD
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
26 /* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
27 typedef int dummy;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
28 #else
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
29
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
30 /* Get the name of the current working directory, and put it in SIZE
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
31 bytes of BUF. Returns NULL if the directory couldn't be determined
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
32 (perhaps because the absolute name was longer than PATH_MAX, or
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
33 because of missing read/search permissions on parent directories)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
34 or SIZE was too small. If successful, returns BUF. If BUF is
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
35 NULL, an array is allocated with `malloc'; the array is SIZE bytes
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
36 long, unless SIZE == 0, in which case it is as big as
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
37 necessary. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
38
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
39 # undef getcwd
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
40 char *
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
41 rpl_getcwd (char *buf, size_t size)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
42 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
43 char *ptr;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
44 char *result;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
45
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
46 /* Handle single size operations. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
47 if (buf)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
48 return getcwd (buf, size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
49
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
50 if (size)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
51 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
52 buf = malloc (size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
53 if (!buf)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
54 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
55 errno = ENOMEM;
14641
9a3f3761a941 getcwd: fix mingw bugs
Eric Blake <eblake@redhat.com>
parents: 14629
diff changeset
56 return NULL;
14629
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
57 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
58 result = getcwd (buf, size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
59 if (!result)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
60 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
61 int saved_errno = errno;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
62 free (buf);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
63 errno = saved_errno;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
64 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
65 return result;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
66 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
67
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
68 /* Flexible sizing requested. Avoid over-allocation for the common
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
69 case of a name that fits within a 4k page, minus some space for
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
70 local variables, to be sure we don't skip over a guard page. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
71 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
72 char tmp[4032];
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
73 size = sizeof tmp;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
74 ptr = getcwd (tmp, size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
75 if (ptr)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
76 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
77 result = strdup (ptr);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
78 if (!result)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
79 errno = ENOMEM;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
80 return result;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
81 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
82 if (errno != ERANGE)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
83 return NULL;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
84 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
85
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
86 /* My what a large directory name we have. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
87 do
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
88 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
89 size <<= 1;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
90 ptr = realloc (buf, size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
91 if (ptr == NULL)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
92 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
93 free (buf);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
94 errno = ENOMEM;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
95 return NULL;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
96 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
97 buf = ptr;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
98 result = getcwd (buf, size);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
99 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
100 while (!result && errno == ERANGE);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
101
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
102 if (!result)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
103 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
104 int saved_errno = errno;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
105 free (buf);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
106 errno = saved_errno;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
107 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
108 else
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
109 {
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
110 /* Trim to fit, if possible. */
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
111 result = realloc (buf, strlen (buf) + 1);
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
112 if (!result)
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
113 result = buf;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
114 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
115 return result;
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
116 }
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
117
7a493fbc787a getcwd-lgpl: new module
Eric Blake <eblake@redhat.com>
parents:
diff changeset
118 #endif