1/* BEGIN LICENSE BLOCK
2 * Version: CMPL 1.1
3 *
4 * The contents of this file are subject to the Cisco-style Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file except
6 * in compliance with the License.  You may obtain a copy of the License
7 * at www.eclipse-clp.org/license.
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See
11 * the License for the specific language governing rights and limitations
12 * under the License.
13 *
14 * The Original Code is  The ECLiPSe Constraint Logic Programming System.
15 * The Initial Developer of the Original Code is  Cisco Systems, Inc.
16 * Portions created by the Initial Developer are
17 * Copyright (C) 1988-2006 Cisco Systems, Inc.  All Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * END LICENSE BLOCK */
22
23/*
24 * VERSION	$Id: getwd.c,v 1.1 2008/06/30 17:43:55 jschimpf Exp $
25*/
26
27/*---------------------------------------------------------------------
28 *
29 * author: 	M.Dorochevsky
30 * modified by:
31 *---------------------------------------------------------------------
32 */
33
34#ifdef SYSDIR
35
36/* #include	<sys/types.h> */	/* all included in bip_misc.c */
37/* #include	<sys/param.h> */
38/* #include	<sys/stat.h> */
39#include	<sys/dir.h>
40
41#define		 FILESYSTEM_READ_ERROR	\
42"getwd(): Filesystem error: read()\nCurrent working directory maybe changed.\n"
43
44
45
46/* char * strcpy(); */
47
48
49
50/*
51 * Copies the pathname of the current working directory into the
52 * buffer path and returns a pointer to this pathname.
53 * Path is a buffer of MAX_PATH_LEN characters.
54 *
55 * If an error occurs, getwd() returns zero ((char *) 0) and leaves
56 * an error message in path
57 */
58
59char * getwd(char *path)
60{
61	struct	stat	dotstat, dotdotstat;
62	struct	direct	dir;
63	int	fd;
64	char * ptail;
65	unsigned len, pathlen;
66	char    statbuf[MAX_PATH_LEN];
67
68	ptail = &(path[MAX_PATH_LEN-1]);
69	*ptail = '\0';
70	pathlen = 0;
71	statbuf[0] = '.';
72	statbuf[1] = '.';
73	statbuf[2] = '/';
74
75	for(;;) {
76	    if(stat(".", &dotstat) < 0) {
77		(void) strcpy(path,"getwd(): stat()\n");
78		goto err;
79	    }
80	    if ((fd = open("..",0)) < 0) {
81		(void) strcpy(path,"getwd(): open()\n");
82		goto err;
83	    }
84	    if(fstat(fd, &dotdotstat) < 0) {
85		(void) strcpy(path,"getwd(): fstat()\n");
86		goto err_close;
87	    }
88
89	    if ((dotstat.st_dev == dotdotstat.st_dev) &&
90		(dotstat.st_ino == dotdotstat.st_ino)) {
91
92		/*
93		 * root reached
94		 */
95		(void) close(fd);
96		break;
97	    }
98	    else {
99
100		/*
101		 * root not reached
102		 */
103		if (pathlen + DIRSIZ + 1 >= MAX_PATH_LEN) {
104		    (void) strcpy(path,"getwd(): Pathname too long.\n");
105		    goto err_close;	/* path name too long */
106		}
107
108		do {
109		    if (read(fd,(char *) &dir,sizeof(dir)) != sizeof(dir)) {
110			(void) strcpy(path, FILESYSTEM_READ_ERROR);
111			goto err_close;
112		    }
113		    (void) strcpy(statbuf + 3, dir.d_name);
114		    (void) stat(statbuf, &dotdotstat);
115		} while ((dotdotstat.st_ino != dotstat.st_ino) ||
116			 (dotdotstat.st_dev != dotstat.st_dev));
117		(void) close(fd);
118	        if(chdir("..") < 0) {
119		    (void) strcpy(path,"getwd(): fopen()\n");
120		    goto err_close;
121		}
122
123		/* copy name to path */
124		{
125		register char * pname;
126
127		pname = dir.d_name;
128		len = 0;
129		while ((len < DIRSIZ) && (*pname++ != '\0'))
130		    len++;
131
132		pathlen += len + 1;
133		for (pname = &(dir.d_name[len]); len; len--)
134		    *--ptail = *--pname;
135		*--ptail = '/';
136		}
137	    }
138	}
139
140	if (pathlen == 0) {
141		path[0] = '/';
142		path[1] = '\0';
143	}
144	else {
145		register char * pto = path;
146		register char * pfrom = ptail;
147
148		for (len = 0; len <= pathlen; len++)
149			*pto++ = *pfrom++;
150
151		/* go back to initial working directory */
152		(void) chdir(ptail+1);
153	}
154
155	return(path);
156
157err_close:
158	(void) close(fd);
159err:
160	/* go back to initial working directory */
161	if (*ptail)
162		(void) chdir(ptail+1);
163	return((char *) 0);
164}
165
166#endif
167
168