| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 | #include <stdlib.h>#include <errno.h>#include <sys/stat.h>#include <dirent.h>#include <string.h>/* These functions find the absolute path to the current working directory.  */static char *recurser();		/* Routine to go up tree */static char *search_dir();		/* Routine to find the step back down */static char *path_buf;static int path_size;static dev_t root_dev;static ino_t root_ino;static struct stat st;char *getcwd( char *buf, int size){	path_size = size;	if (size < 3) {		__set_errno(ERANGE);		return NULL;	}	if (buf != NULL)	    path_buf = buf;	else	{	    path_buf = malloc (size);	    if (path_buf == NULL)		return NULL;	}	strcpy(path_buf, ".");	if (stat("/", &st) < 0)		return NULL;	root_dev = st.st_dev;	root_ino = st.st_ino;	return recurser();}static char *recurser(){	dev_t this_dev;	ino_t this_ino;	if (stat(path_buf, &st) < 0)		return 0;	this_dev = st.st_dev;	this_ino = st.st_ino;	if (this_dev == root_dev && this_ino == root_ino) {		strcpy(path_buf, "/");		return path_buf;	}	if (strlen(path_buf) + 4 > path_size) {		__set_errno(ERANGE);		return 0;	}	strcat(path_buf, "/..");	if (recurser() == 0)		return 0;	return search_dir(this_dev, this_ino);}static char *search_dir(this_dev, this_ino)dev_t this_dev;ino_t this_ino;{	DIR *dp;	struct dirent *d;	char *ptr;	int slen;	/* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */	int slow_search = (sizeof(ino_t) != sizeof(d->d_ino));	if (stat(path_buf, &st) < 0)		return 0;	if (this_dev != st.st_dev)		slow_search = 1;	slen = strlen(path_buf);	ptr = path_buf + slen - 1;	if (*ptr != '/') {		if (slen + 2 > path_size) {			__set_errno(ERANGE);			return 0;		}		strcpy(++ptr, "/");		slen++;	}	slen++;	dp = opendir(path_buf);	if (dp == 0)		return 0;	while ((d = readdir(dp)) != 0) {		if (slow_search || this_ino == d->d_ino) {			if (slen + strlen(d->d_name) > path_size) {				__set_errno(ERANGE);				return 0;			}			strcpy(ptr + 1, d->d_name);			if (stat(path_buf, &st) < 0)				continue;			if (st.st_ino == this_ino && st.st_dev == this_dev) {				closedir(dp);				return path_buf;			}		}	}	closedir(dp);	__set_errno(ENOENT);	return 0;}
 |