2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: getcwd.c /main/3 1995/11/01 17:56:20 rswiston $ */
24 /***************************************************************
26 * AT&T - PROPRIETARY *
28 * THIS IS PROPRIETARY SOURCE CODE LICENSED BY *
31 * Copyright (c) 1995 AT&T Corp. *
32 * All Rights Reserved *
34 * This software is licensed by AT&T Corp. *
35 * under the terms and conditions of the license in *
36 * http://www.research.att.com/orgs/ssr/book/reuse *
38 * This software was created by the *
39 * Software Engineering Research Department *
40 * AT&T Bell Laboratories *
42 * For further information contact *
43 * gsf@research.att.com *
45 ***************************************************************/
47 /* : : generated by proto : : */
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__ "C"
57 #define __PROTO__(x) x
59 #define __PARAM__(n,o) n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
72 #define __PROTO__(x) ()
73 #define __OTORP__(x) x
74 #define __PARAM__(n,o) o
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__ ...
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a) va_start(p,a)
90 #define __VA_START__(p,a) va_start(p)
101 #define ERROR(e) { errno = e; goto error; }
103 struct dirlist /* long path chdir(2) component */
105 struct dirlist* next; /* next component */
106 int index; /* index from end of buf */
110 * pop long dir component chdir stack
114 popdir __PARAM__((register struct dirlist* d, register char* end), (d, end)) __OTORP__(register struct dirlist* d; register char* end;){
115 register struct dirlist* dp;
124 if (d) *(end - d->index - 1) = 0;
125 v = chdir(end - dp->index);
126 if (d) *(end - d->index - 1) = '/';
134 * push long dir component onto stack
137 static struct dirlist*
138 pushdir __PARAM__((register struct dirlist* d, char* dots, char* path, char* end), (d, dots, path, end)) __OTORP__(register struct dirlist* d; char* dots; char* path; char* end;){
139 register struct dirlist* p;
141 if (!(p = newof(0, struct dirlist, 1, 0)) || chdir(dots))
144 if (d) popdir(d, end);
147 p->index = end - path;
153 * return a pointer to the absolute path name of .
154 * this path name may be longer than PATH_MAX
156 * a few environment variables are checked before the search algorithm
157 * return value is placed in buf of len chars
158 * if buf is 0 then space is allocated via malloc() with
159 * len extra chars after the path name
160 * 0 is returned on error with errno set as appropriate
164 getcwd __PARAM__((char* buf, size_t len), (buf, len)) __OTORP__(char* buf; size_t len;){
173 struct dirent* entry;
174 struct dirlist* dirstk = 0;
195 if (buf && !len) ERROR(EINVAL);
196 if (fs3d(FS3D_TEST) && (namlen = mount(".", dots, FS3D_GET|FS3D_VIEW|FS3D_SIZE(sizeof(dots)), NiL)) > 1 && namlen < sizeof(dots))
203 if (len < namlen) ERROR(ERANGE);
205 else if (!(buf = newof(0, char, namlen, len))) ERROR(ENOMEM);
206 return((char*)memcpy(buf, p, namlen));
210 if (stat(".", par)) ERROR(errno);
211 for (n = 0; n < elementsof(env); n++)
213 if ((p = getenv(env[n].name)) && *p == '/' && !stat(p, cur))
216 env[n].dev = cur->st_dev;
217 env[n].ino = cur->st_ino;
218 if (cur->st_ino == par->st_ino && cur->st_dev == par->st_dev)
229 if (!(buf = newof(0, char, len, extra))) ERROR(ENOMEM);
240 if ((d - dots) > (PATH_MAX - 4))
242 if (!(dirstk = pushdir(dirstk, dots, p, buf + len - 1))) ERROR(ERANGE);
248 if (!(dirp = opendir(dots))) ERROR(errno);
249 #if !_dir_ok || _mem_dd_fd_DIR
250 if (fstat(dirp->dd_fd, par)) ERROR(errno);
252 if (stat(dots, par)) ERROR(errno);
255 if (par->st_dev == cur->st_dev)
257 if (par->st_ino == cur->st_ino)
267 if (extra >= 0 && !(buf = newof(buf, char, len, extra))) ERROR(ENOMEM);
269 if (dirstk && popdir(dirstk, buf + len - 1))
276 #if _mem_d_fileno_dirent || _mem_d_ino_dirent
277 #if !_mem_d_fileno_dirent
278 #define d_fileno d_ino
280 while (entry = readdir(dirp))
281 if (entry->d_fileno == cur->st_ino)
283 #if _mem_d_namlen_dirent
284 namlen = entry->d_namlen;
286 namlen = strlen(entry->d_name);
293 * this fallthrough handles logical naming
300 if (!(entry = readdir(dirp))) ERROR(ENOENT);
301 #if _mem_d_namlen_dirent
302 namlen = entry->d_namlen;
304 namlen = strlen(entry->d_name);
306 if ((d - dots) > (PATH_MAX - 1 - namlen))
309 if (namlen >= PATH_MAX || !(dirstk = pushdir(dirstk, dots + 3, p, buf + len - 1))) ERROR(ERANGE);
312 memcpy(d, entry->d_name, namlen + 1);
313 } while (stat(dots, &tstst) || tstst.st_ino != cur->st_ino || tstst.st_dev != cur->st_dev);
316 while ((p -= namlen) <= (buf + 1))
318 x = (buf + len - 1) - (p += namlen);
320 if (extra < 0 || !(buf = newof(buf, char, len += PATH_MAX, extra))) ERROR(ERANGE);
322 while (p > buf + len - 1 - x) *--p = *--s;
324 if (n < elementsof(env))
326 memcpy(p, env[n].path, namlen);
329 memcpy(p, entry->d_name, namlen);
332 for (n = 0; n < elementsof(env); n++)
333 if (env[n].ino == par->st_ino && env[n].dev == par->st_dev)
335 namlen = strlen(env[n].path);
342 if (dirstk) popdir(dirstk, buf + len - 1);
343 if (extra >= 0) free(buf);
345 if (dirp) closedir(dirp);