123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /* getcwd - get current working directory Author: Terrence W. Holm */
- /* Directly derived from Adri Koppes' pwd(1).
- * Modified by Andy Tanenbaum for POSIX (29 Oct. 1989)
- */
- #include <lib.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/dir.h>
- #include <string.h>
- #define getcwd _getcwd
- #define DIRECT_SIZE (sizeof (struct direct))
- PRIVATE _PROTOTYPE(void go_back, (char *path) );
- char *getcwd(buffer, size)
- char *buffer;
- int size;
- /* Get current working directory. */
- {
- int same_device, found, fd;
- char *r, path[PATH_MAX + 1], temp_name[NAME_MAX + 1];
- struct stat current, parent, dir_entry;
- struct direct d;
- if (buffer == (char *)NULL || size <= 0) {
- errno = EINVAL;
- return((char *)NULL);
- }
- path[0] = '\0';
- /* Get the inode for the current directory */
- if (stat(".", ¤t) == -1) return((char *)NULL);
- if ((current.st_mode & S_IFMT) != S_IFDIR) return((char *)NULL);
- /* Run backwards up the directory tree, grabbing dir names on the way. */
- while (1) {
- same_device = 0;
- found = 0;
- /* Get the inode for the parent directory */
- if (chdir("..") == -1) return((char *)NULL);
- if (stat(".", &parent) == -1) return((char *)NULL);
- if ((parent.st_mode & S_IFMT) != S_IFDIR) return((char *)NULL);
- if (current.st_dev == parent.st_dev) same_device = 1;
- /* At the root, "." is the same as ".." */
- if (same_device && current.st_ino == parent.st_ino) break;
- /* Search the parent directory for the current entry */
- if ((fd = open(".", O_RDONLY)) == -1) return((char *)NULL);
- while (!found && read(fd, (char *)&d, DIRECT_SIZE) == DIRECT_SIZE) {
- if (d.d_ino == 0L) continue; /* empty slot */
- if (same_device) {
- if (current.st_ino == d.d_ino) found = 1;
- } else {
- temp_name[0] = '\0';
- strncat(temp_name, d.d_name, NAME_MAX);
- if (stat(temp_name, &dir_entry) == -1) {
- close(fd);
- go_back(path);
- return((char *)NULL);
- }
- if (current.st_dev == dir_entry.st_dev &&
- current.st_ino == dir_entry.st_ino)
- found = 1;
- }
- }
- close(fd);
- if (!found) {
- go_back(path);
- return((char *)NULL);
- }
- if (strlen(path) + NAME_MAX + 1 > PATH_MAX) {
- errno = ERANGE;
- go_back(path);
- return((char *)NULL);
- }
- strcat(path, "/");
- strncat(path, d.d_name, NAME_MAX);
- current.st_dev = parent.st_dev;
- current.st_ino = parent.st_ino;
- }
- /* Copy the reversed path name into <buffer> */
- if (strlen(path) + 1 > size) {
- errno = ERANGE;
- go_back(path);
- return((char *)NULL);
- }
- if (strlen(path) == 0) {
- strcpy(buffer, "/");
- return(buffer);
- }
- *buffer = '\0';
- while ((r = strrchr(path, '/')) != (char *)NULL) {
- strcat(buffer, r);
- *r = '\0';
- }
- return(chdir(buffer) ? (char *)NULL : buffer);
- }
- PRIVATE void go_back(path)
- char *path;
- {
- /* If getcwd() gets in trouble and can't complete normally, reverse the
- * path built so far and change there so we end up in the directory that
- * we started in.
- */
- char *r;
- while ((r = strrchr(path, '/')) != (char *)NULL) {
- chdir(r+1);
- *r = '\0';
- }
- }
|