~ubuntu-branches/ubuntu/trusty/bash/trusty-security

« back to all changes in this revision

Viewing changes to lib/sh/getcwd.c

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2014-03-03 22:52:05 UTC
  • mfrom: (1.3.5) (2.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20140303225205-87ltrt5kspeq0g1b
Tags: 4.3-1ubuntu1
* Merge with Debian; remaining changes:
  - skel.bashrc:
    - Run lesspipe.
    - Enable ls aliases.
    - Set options in ll alias to -alF.
    - Define an alert alias.
    - Enabled colored grep aliases.
  - etc.bash.bashrc:
    - Add sudo hint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* getcwd.c -- get pathname of current directory */
 
2
 
 
3
/* Copyright (C) 1991 Free Software Foundation, Inc.
 
4
 
 
5
   This file is part of GNU Bash, the Bourne Again SHell.
 
6
 
 
7
   Bash is free software: you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation, either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
 
 
12
   Bash is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
 
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
 
19
*/
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#if !defined (HAVE_GETCWD)
 
24
 
 
25
#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
 
26
  #pragma alloca
 
27
#endif /* _AIX && RISC6000 && !__GNUC__ */
 
28
 
 
29
#if defined (__QNX__)
 
30
#  undef HAVE_LSTAT
 
31
#endif
 
32
 
 
33
#include <bashtypes.h>
 
34
#include <errno.h>
 
35
 
 
36
#if defined (HAVE_LIMITS_H)
 
37
#  include <limits.h>
 
38
#endif
 
39
 
 
40
#if defined (HAVE_UNISTD_H)
 
41
#  include <unistd.h>
 
42
#endif
 
43
 
 
44
#include <posixdir.h>
 
45
#include <posixstat.h>
 
46
#include <maxpath.h>
 
47
#include <memalloc.h>
 
48
 
 
49
#include <bashansi.h>
 
50
 
 
51
#if !defined (D_FILENO_AVAILABLE)
 
52
#  include "command.h"
 
53
#  include "general.h"
 
54
#  include "externs.h"
 
55
#endif
 
56
 
 
57
#include <xmalloc.h>
 
58
 
 
59
#if !defined (errno)
 
60
extern int errno;
 
61
#endif /* !errno */
 
62
 
 
63
#if !defined (HAVE_LSTAT)
 
64
#  define lstat stat
 
65
#endif
 
66
 
 
67
#if !defined (NULL)
 
68
#  define NULL 0
 
69
#endif
 
70
 
 
71
/* If the d_fileno member of a struct dirent doesn't return anything useful,
 
72
   we need to check inode number equivalence the hard way.  Return 1 if
 
73
   the inode corresponding to PATH/DIR is identical to THISINO. */
 
74
#if !defined (D_FILENO_AVAILABLE)
 
75
static int
 
76
_path_checkino (dotp, name, thisino)
 
77
     char *dotp;
 
78
     char *name;
 
79
     ino_t thisino;
 
80
{
 
81
  char *fullpath;
 
82
  int r, e;
 
83
  struct stat st;
 
84
 
 
85
  e = errno;
 
86
  fullpath = sh_makepath (dotp, name, MP_RMDOT);
 
87
  if (stat (fullpath, &st) < 0)
 
88
    {
 
89
      errno = e;
 
90
      return 0;
 
91
    }
 
92
  free (fullpath);
 
93
  errno = e;
 
94
  return (st.st_ino == thisino);
 
95
}
 
96
#endif
 
97
    
 
98
/* Get the pathname of the current working directory,
 
99
   and put it in SIZE bytes of BUF.  Returns NULL if the
 
100
   directory couldn't be determined or SIZE was too small.
 
101
   If successful, returns BUF.  In GNU, if BUF is NULL,
 
102
   an array is allocated with `malloc'; the array is SIZE
 
103
   bytes long, unless SIZE <= 0, in which case it is as
 
104
   big as necessary.  */
 
105
#if defined (__STDC__)
 
106
char *
 
107
getcwd (char *buf, size_t size)
 
108
#else /* !__STDC__ */
 
109
char *
 
110
getcwd (buf, size)
 
111
     char *buf;
 
112
     size_t size;
 
113
#endif /* !__STDC__ */
 
114
{
 
115
  static const char dots[]
 
116
    = "../../../../../../../../../../../../../../../../../../../../../../../\
 
117
../../../../../../../../../../../../../../../../../../../../../../../../../../\
 
118
../../../../../../../../../../../../../../../../../../../../../../../../../..";
 
119
  const char *dotp, *dotlist;
 
120
  size_t dotsize;
 
121
  dev_t rootdev, thisdev;
 
122
  ino_t rootino, thisino;
 
123
  char path[PATH_MAX + 1];
 
124
  register char *pathp;
 
125
  char *pathbuf;
 
126
  size_t pathsize;
 
127
  struct stat st;
 
128
  int saved_errno;
 
129
 
 
130
  if (buf != NULL && size == 0)
 
131
    {
 
132
      errno = EINVAL;
 
133
      return ((char *)NULL);
 
134
    }
 
135
 
 
136
  pathsize = sizeof (path);
 
137
  pathp = &path[pathsize];
 
138
  *--pathp = '\0';
 
139
  pathbuf = path;
 
140
 
 
141
  if (stat (".", &st) < 0)
 
142
    return ((char *)NULL);
 
143
  thisdev = st.st_dev;
 
144
  thisino = st.st_ino;
 
145
 
 
146
  if (stat ("/", &st) < 0)
 
147
    return ((char *)NULL);
 
148
  rootdev = st.st_dev;
 
149
  rootino = st.st_ino;
 
150
 
 
151
  saved_errno = 0;
 
152
 
 
153
  dotsize = sizeof (dots) - 1;
 
154
  dotp = &dots[sizeof (dots)];
 
155
  dotlist = dots;
 
156
  while (!(thisdev == rootdev && thisino == rootino))
 
157
    {
 
158
      register DIR *dirstream;
 
159
      register struct dirent *d;
 
160
      dev_t dotdev;
 
161
      ino_t dotino;
 
162
      char mount_point;
 
163
      int namlen;
 
164
 
 
165
      /* Look at the parent directory.  */
 
166
      if (dotp == dotlist)
 
167
        {
 
168
          /* My, what a deep directory tree you have, Grandma.  */
 
169
          char *new;
 
170
          if (dotlist == dots)
 
171
            {
 
172
              new = (char *)malloc (dotsize * 2 + 1);
 
173
              if (new == NULL)
 
174
                goto lose;
 
175
              memcpy (new, dots, dotsize);
 
176
            }
 
177
          else
 
178
            {
 
179
              new = (char *)realloc ((PTR_T) dotlist, dotsize * 2 + 1);
 
180
              if (new == NULL)
 
181
                goto lose;
 
182
            }
 
183
          memcpy (&new[dotsize], new, dotsize);
 
184
          dotp = &new[dotsize];
 
185
          dotsize *= 2;
 
186
          new[dotsize] = '\0';
 
187
          dotlist = new;
 
188
        }
 
189
 
 
190
      dotp -= 3;
 
191
 
 
192
      /* Figure out if this directory is a mount point.  */
 
193
      if (stat (dotp, &st) < 0)
 
194
        goto lose;
 
195
      dotdev = st.st_dev;
 
196
      dotino = st.st_ino;
 
197
      mount_point = dotdev != thisdev;
 
198
 
 
199
      /* Search for the last directory.  */
 
200
      dirstream = opendir (dotp);
 
201
      if (dirstream == NULL)
 
202
        goto lose;
 
203
      while ((d = readdir (dirstream)) != NULL)
 
204
        {
 
205
          if (d->d_name[0] == '.' &&
 
206
              (d->d_name[1] == '\0' ||
 
207
                (d->d_name[1] == '.' && d->d_name[2] == '\0')))
 
208
            continue;
 
209
#if defined (D_FILENO_AVAILABLE)
 
210
          if (mount_point || d->d_fileno == thisino)
 
211
#else
 
212
          if (mount_point || _path_checkino (dotp, d->d_name, thisino))
 
213
#endif
 
214
            {
 
215
              char *name;
 
216
 
 
217
              namlen = D_NAMLEN(d);
 
218
              name = (char *)
 
219
                alloca (dotlist + dotsize - dotp + 1 + namlen + 1);
 
220
              memcpy (name, dotp, dotlist + dotsize - dotp);
 
221
              name[dotlist + dotsize - dotp] = '/';
 
222
              memcpy (&name[dotlist + dotsize - dotp + 1],
 
223
                      d->d_name, namlen + 1);
 
224
              if (lstat (name, &st) < 0)
 
225
                {
 
226
#if 0
 
227
                  int save = errno;
 
228
                  (void) closedir (dirstream);
 
229
                  errno = save;
 
230
                  goto lose;
 
231
#else
 
232
                  saved_errno = errno;
 
233
#endif
 
234
                }
 
235
              if (st.st_dev == thisdev && st.st_ino == thisino)
 
236
                break;
 
237
            }
 
238
        }
 
239
      if (d == NULL)
 
240
        {
 
241
#if 0
 
242
          int save = errno;
 
243
#else
 
244
          int save = errno ? errno : saved_errno;
 
245
#endif
 
246
          (void) closedir (dirstream);
 
247
          errno = save;
 
248
          goto lose;
 
249
        }
 
250
      else
 
251
        {
 
252
          size_t space;
 
253
 
 
254
          while ((space = pathp - pathbuf) <= namlen)
 
255
            {
 
256
              char *new;
 
257
 
 
258
              if (pathbuf == path)
 
259
                {
 
260
                  new = (char *)malloc (pathsize * 2);
 
261
                  if (!new)
 
262
                    goto lose;
 
263
                }
 
264
              else
 
265
                {
 
266
                  new = (char *)realloc ((PTR_T) pathbuf, (pathsize * 2));
 
267
                  if (!new)
 
268
                    goto lose;
 
269
                  pathp = new + space;
 
270
                }
 
271
              (void) memcpy (new + pathsize + space, pathp, pathsize - space);
 
272
              pathp = new + pathsize + space;
 
273
              pathbuf = new;
 
274
              pathsize *= 2;
 
275
            }
 
276
 
 
277
          pathp -= namlen;
 
278
          (void) memcpy (pathp, d->d_name, namlen);
 
279
          *--pathp = '/';
 
280
          (void) closedir (dirstream);
 
281
        }
 
282
 
 
283
      thisdev = dotdev;
 
284
      thisino = dotino;
 
285
    }
 
286
 
 
287
  if (pathp == &path[sizeof(path) - 1])
 
288
    *--pathp = '/';
 
289
 
 
290
  if (dotlist != dots)
 
291
    free ((PTR_T) dotlist);
 
292
 
 
293
  {
 
294
    size_t len = pathbuf + pathsize - pathp;
 
295
    if (buf == NULL && size <= 0)
 
296
      size = len;
 
297
 
 
298
    if ((size_t) size < len)
 
299
      {
 
300
        errno = ERANGE;
 
301
        goto lose2;
 
302
      }
 
303
    if (buf == NULL)
 
304
      {
 
305
        buf = (char *) malloc (size);
 
306
        if (buf == NULL)
 
307
          goto lose2;
 
308
      }
 
309
 
 
310
    (void) memcpy((PTR_T) buf, (PTR_T) pathp, len);
 
311
  }
 
312
 
 
313
  if (pathbuf != path)
 
314
    free (pathbuf);
 
315
 
 
316
  return (buf);
 
317
 
 
318
 lose:
 
319
  if ((dotlist != dots) && dotlist)
 
320
    {
 
321
      int e = errno;
 
322
      free ((PTR_T) dotlist);
 
323
      errno = e;
 
324
    }
 
325
 
 
326
 lose2:
 
327
  if ((pathbuf != path) && pathbuf)
 
328
    {
 
329
      int e = errno;
 
330
      free ((PTR_T) pathbuf);
 
331
      errno = e;
 
332
    }
 
333
  return ((char *)NULL);
 
334
}
 
335
 
 
336
#if defined (TEST)
 
337
#  include <stdio.h>
 
338
main (argc, argv)
 
339
     int argc;
 
340
     char **argv;
 
341
{
 
342
  char b[PATH_MAX];
 
343
 
 
344
  if (getcwd(b, sizeof(b)))
 
345
    {
 
346
      printf ("%s\n", b);
 
347
      exit (0);
 
348
    }
 
349
  else
 
350
    {
 
351
      perror ("cwd: getcwd");
 
352
      exit (1);
 
353
    }
 
354
}
 
355
#endif /* TEST */
 
356
#endif /* !HAVE_GETCWD */