OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [newlib-1.18.0/] [newlib/] [libc/] [unix/] [getcwd.c] - Blame information for rev 816

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 207 jeremybenn
#ifndef _NO_GETCWD
2
/*
3
 * Copyright (c) 1989, 1991 The Regents of the University of California.
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 4. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
 
31
#if defined(LIBC_SCCS) && !defined(lint)
32
static char sccsid[] = "@(#)getcwd.c    5.11 (Berkeley) 2/24/91";
33
#endif /* LIBC_SCCS and not lint */
34
 
35
#include <sys/stat.h>
36
#include <errno.h>
37
#include <dirent.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <unistd.h>
42
#include <reent.h>
43
#include <_syslist.h>
44
 
45
#define bcopy(a,b,c)    memmove (b,a,c)
46
 
47
#define ISDOT(dp) \
48
        (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
49
           (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
50
 
51
#ifndef _REENT_ONLY
52
 
53
char *
54
getcwd (pt, size)
55
     char *pt;
56
     size_t size;
57
{
58
  register struct dirent *dp;
59
  register DIR *dir;
60
  register dev_t dev;
61
  register ino_t ino;
62
  register int first;
63
  register char *bpt, *bup;
64
  struct stat s;
65
  dev_t root_dev;
66
  ino_t root_ino;
67
  size_t ptsize, upsize;
68
  int save_errno;
69
  char *ept, *eup, *up;
70
 
71
  /*
72
   * If no buffer specified by the user, allocate one as necessary.
73
   * If a buffer is specified, the size has to be non-zero.  The path
74
   * is built from the end of the buffer backwards.
75
   */
76
 
77
  if (pt)
78
    {
79
      ptsize = 0;
80
      if (!size)
81
        {
82
          errno = EINVAL;
83
          return (char *) NULL;
84
        }
85
      ept = pt + size;
86
    }
87
  else
88
    {
89
      if (!(pt = (char *) malloc (ptsize = 1024 - 4)))
90
        {
91
          return (char *) NULL;
92
        }
93
      ept = pt + ptsize;
94
    }
95
  bpt = ept - 1;
96
  *bpt = '\0';
97
 
98
  /*
99
   * Allocate bytes (1024 - malloc space) for the string of "../"'s.
100
   * Should always be enough (it's 340 levels).  If it's not, allocate
101
   * as necessary.  Special * case the first stat, it's ".", not "..".
102
   */
103
 
104
  if (!(up = (char *) malloc (upsize = 1024 - 4)))
105
    {
106
      goto err;
107
    }
108
  eup = up + MAXPATHLEN;
109
  bup = up;
110
  up[0] = '.';
111
  up[1] = '\0';
112
 
113
  /* Save root values, so know when to stop. */
114
  if (stat ("/", &s))
115
    goto err;
116
  root_dev = s.st_dev;
117
  root_ino = s.st_ino;
118
 
119
  errno = 0;                     /* XXX readdir has no error return. */
120
 
121
  for (first = 1;; first = 0)
122
    {
123
      /* Stat the current level. */
124
      if (stat (up, &s))
125
        goto err;
126
 
127
      /* Save current node values. */
128
      ino = s.st_ino;
129
      dev = s.st_dev;
130
 
131
      /* Check for reaching root. */
132
      if (root_dev == dev && root_ino == ino)
133
        {
134
          *--bpt = '/';
135
          /*
136
           * It's unclear that it's a requirement to copy the
137
           * path to the beginning of the buffer, but it's always
138
           * been that way and stuff would probably break.
139
           */
140
          (void) bcopy (bpt, pt, ept - bpt);
141
          free (up);
142
          return pt;
143
        }
144
 
145
      /*
146
       * Build pointer to the parent directory, allocating memory
147
       * as necessary.  Max length is 3 for "../", the largest
148
       * possible component name, plus a trailing NULL.
149
       */
150
 
151
      if (bup + 3 + MAXNAMLEN + 1 >= eup)
152
        {
153
          if (!(up = (char *) realloc (up, upsize *= 2)))
154
            {
155
              goto err;
156
            }
157
          bup = up;
158
          eup = up + upsize;
159
        }
160
      *bup++ = '.';
161
      *bup++ = '.';
162
      *bup = '\0';
163
 
164
      /* Open and stat parent directory. */
165
      if (!(dir = opendir (up)) || fstat (__dirfd (dir), &s))
166
        goto err;
167
 
168
      /* Add trailing slash for next directory. */
169
      *bup++ = '/';
170
 
171
      /*
172
       * If it's a mount point, have to stat each element because
173
       * the inode number in the directory is for the entry in the
174
       * parent directory, not the inode number of the mounted file.
175
       */
176
 
177
      save_errno = 0;
178
      if (s.st_dev == dev)
179
        {
180
          for (;;)
181
            {
182
              if (!(dp = readdir (dir)))
183
                goto notfound;
184
              if (dp->d_ino == ino)
185
                break;
186
            }
187
        }
188
      else
189
        for (;;)
190
          {
191
            if (!(dp = readdir (dir)))
192
              goto notfound;
193
            if (ISDOT (dp))
194
              continue;
195
            bcopy (dp->d_name, bup, strlen (dp->d_name) + 1);
196
 
197
            /* Save the first error for later. */
198
            if (stat (up, &s))
199
              {
200
                if (!save_errno)
201
                  save_errno = errno;
202
                errno = 0;
203
                continue;
204
              }
205
            if (s.st_dev == dev && s.st_ino == ino)
206
              break;
207
          }
208
 
209
      /*
210
       * Check for length of the current name, preceding slash,
211
       * leading slash.
212
       */
213
 
214
      if (bpt - pt <= strlen (dp->d_name) + (first ? 1 : 2))
215
        {
216
          size_t len, off;
217
 
218
          if (!ptsize)
219
            {
220
              errno = ERANGE;
221
              goto err;
222
            }
223
          off = bpt - pt;
224
          len = ept - bpt;
225
          if (!(pt = (char *) realloc (pt, ptsize *= 2)))
226
            {
227
              goto err;
228
            }
229
          bpt = pt + off;
230
          ept = pt + ptsize;
231
          (void) bcopy (bpt, ept - len, len);
232
          bpt = ept - len;
233
        }
234
      if (!first)
235
        *--bpt = '/';
236
      bpt -= strlen (dp->d_name);
237
      bcopy (dp->d_name, bpt, strlen (dp->d_name));
238
      (void) closedir (dir);
239
 
240
      /* Truncate any file name. */
241
      *bup = '\0';
242
    }
243
 
244
notfound:
245
  /*
246
   * If readdir set errno, use it, not any saved error; otherwise,
247
   * didn't find the current directory in its parent directory, set
248
   * errno to ENOENT.
249
   */
250
 
251
  if (!errno)
252
    errno = save_errno ? save_errno : ENOENT;
253
  /* FALLTHROUGH */
254
 
255
err:
256
  if (ptsize)
257
    free (pt);
258
  free (up);
259
  return (char *) NULL;
260
}
261
 
262
#endif /* _REENT_ONLY */
263
#endif /* !_NO_GETCWD  */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.