pefv700@perv.pe.utexas.edu (01/11/91)
Like the subject says, I want to get the current working directory. According to my SunOS man page on getwd(3), getwd(buf) will put the absolute path of the current working directory in buf UNLESS there is an error, in which case buf contains some message. The problem is, you don't know if you got the directory name or the message. I can't find any other std library function or system call that will get the job done right (using malloc if necessary). So...to write a "good" getwd, it seems you would have to do something ugly like (skipping error checking) getwd(buf) char *buf; { ino_t inode; struct stat stbuf; DIR *dfd; struct dirent *dp; stat(".", &stbuf); inode = stbuf.st_ino; if (. is /) { /* not sure how to do this, stat .. and check inodes? */ change buf to include / using [m,re]alloc as necessary return; } else chdir(".."); dfd = opendir("."); while ((dp = readdir(dfd)) != NULL) { stat(dp->d_name, &stbuf); if (stbuf.st_ino == inode) { change buf to include dp->d_name using [m,re]alloc as necessary break; } getwd(buf); } Is there a better way, a function I'm missing...? Thanks, Chris
pfalstad@phoenix.Princeton.EDU (Paul John Falstad) (01/11/91)
In article <42380@ut-emx.uucp> pefv700@perv.pe.utexas.edu writes: >According to my SunOS man page on getwd(3), getwd(buf) will put the absolute >path of the current working directory in buf UNLESS there is an error, in >which case buf contains some message. The problem is, you don't know if you >got the directory name or the message. Yes, you do. If there is an error, getwd returns NULL. Otherwise it returns the address of the buffer. Here is a version of getwd I wrote for zsh. I'd be interested in what people think of it. I needed a version that didn't fork(), and was having problems with the Sun getwd(). char *getwd(void) { static char buf0[MAXPATHLEN]; char buf3[MAXPATHLEN],*buf2 = buf0+1; struct stat sbuf; struct direct *de; DIR *dir; ino_t ino = -1; dev_t dev = -1; buf2[0] = '\0'; buf0[0] = '/'; for(;;) { if (stat(".",&sbuf) < 0) { chdir(buf0); return NULL; } ino = sbuf.st_ino; dev = sbuf.st_dev; if (stat("..",&sbuf) < 0) { chdir(buf0); return NULL; } if (sbuf.st_ino == ino && sbuf.st_dev == dev) { /* we're done */ chdir(buf0); return strdup(buf0); } dir = opendir(".."); if (!dir) { chdir(buf0); return NULL; } chdir(".."); readdir(dir); readdir(dir); while (de = readdir(dir)) if (de->d_fileno == ino) { /* find file with matching inode */ lstat(de->d_name,&sbuf); if (sbuf.st_dev == dev) goto match; } rewinddir(dir); readdir(dir); readdir(dir); while (de = readdir(dir)) { lstat(de->d_name,&sbuf); if (sbuf.st_dev == dev) /* find file with matching device # */ goto match; } closedir(dir); return NULL; match: strcpy(buf3,de->d_name); if (*buf2) strcat(buf3,"/"); strcat(buf3,buf2); strcpy(buf2,buf3); closedir(dir); } } -- Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD "We could nuke Baghdad into glass, wipe it with Windex, tie fatback on our feet and go skating." - Air Force Times columnist Fred Reed
denap@alta.sw.stratus.com (Tom DeNapoli) (01/12/91)
Along the same lines... Has anyone got anything that will return the absolute pathname of an open file to a process? Process A has file ./dir1/dir2/foo open and he wants the absolute path to the file as in /usr/local/stuff/dir1/dir2. Ultimately I need to relay this info to Process B and prepend the automount (SunOS 4.1) point to the pathname. As in /net/freddie/usr/local/stuff/dir1/dir2/foo. thanks in advance. -Tom -- Tom DeNapoli | Stratus Computer, Inc. denap@alta.sw.stratus.com | 55 Fairbanks Blvd M23EN3 uunet!lectroid!alta!denap | Marlboro, MA 01752
6sigma2@polari.UUCP (Brian Matthews) (01/13/91)
In article <5195@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU (Paul John Falstad) writes: |Here is a version of getwd I wrote for zsh. I'd be interested in what |people think of it. I needed a version that didn't fork(), and was |having problems with the Sun getwd(). [getwd that crawls up the directory tree reading each directory on the way] The problem with this is that it's quite possible to be in a directory which has some ancestors that can't be read. Thus a program calling this getwd must be running setuid root or in a restricted environment (in which case it probably shouldn't need to call getwd) where it knows all ancestors of the current directory are readable. -- Brian L. Matthews 6sigma2@polari.UUCP
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (01/14/91)
In article <DENAP.91Jan11134939@alta.sw.stratus.com> denap@alta.sw.stratus.com (Tom DeNapoli) writes: >Along the same lines... > >Has anyone got anything that will return the absolute pathname of >an open file to a process? > >Process A has file ./dir1/dir2/foo open and he wants the absolute >path to the file as in /usr/local/stuff/dir1/dir2. > A way to do this is to chdir() to the directory of the file (i.e. dir1/dir2) and then do a getcwd() to find out where absolutely where you are, like this: /* # include <sys/param.h> */ char fullpath[MAXPATHLEN]; chdir("dir1/dir2"); getcwd(fullpath, MAXPATHLEN); printf("Full pathname is %s\n", fullpath); -Kartik Newsgroups: comp.unix.programmer Subject: Re: getting the current working directory Summary: Expires: References: <42380@ut-emx.uucp> <DENAP.91Jan11134939@alta.sw.stratus.com> Sender: Followup-To: Distribution: usa Organization: Keywords: In article <DENAP.91Jan11134939@alta.sw.stratus.com> denap@alta.sw.stratus.com (Tom DeNapoli) writes: >Along the same lines... > >Has anyone got anything that will return the absolute pathname of >an open file to a process? > >Process A has file ./dir1/dir2/foo open and he wants the absolute >path to the file as in /usr/local/stuff/dir1/dir2. > A way to do this is to chdir() to the directory of the file (i.e. dir1/dir2) and then do a getcwd() to find out where absolutely where you are, like this: /* # include <sys/param.h> */ char fullpath[MAXPATHLEN]; chdir("dir1/dir2"); getcwd(fullpath, MAXPATHLEN); printf("Full pathname is %s\n", fullpath); -Kartik -- internet# ls -alR | grep *.c subbarao@{phoenix or gauguin}.Princeton.EDU -|Internet kartik@silvertone.Princeton.EDU (NeXT mail) -| SUBBARAO@PUCC.BITNET - Bitnet
guy@auspex.auspex.com (Guy Harris) (01/16/91)
>[getwd that crawls up the directory tree reading each directory on the way] > >The problem with this is that it's quite possible to be in a directory >which has some ancestors that can't be read. Thus a program calling this >getwd must be running setuid root or in a restricted environment (in which >case it probably shouldn't need to call getwd) where it knows all ancestors >of the current directory are readable. A program calling just about *any* flavor of "getwd()" must be running set-uid "root" or in a restricted environment of that sort if you actually care about getting the right answer in a directory that has some ancestors that can't be read. The 4.xBSD "getwd()" and SunOS "getwd()"s, just like the posted one, crawl up the directory tree reading each directory on the way. Prior to S5R4, S5's "getcwd()" "popen()"ed a "pwd" program, but I don't think "pwd" is set-UID "root" in S5. I think S5R4's is a subroutine that crawls up the directory tree, just like many (all?) "getwd()"s. Note also that in the presence of various distributed file systems even set-UID "root" may not be enough; both NFS and RFS servers may map the root user-ID to some unprivileged user ID.
chip@tct.uucp (Chip Salzenberg) (01/17/91)
According to guy@auspex.auspex.com (Guy Harris): >Note also that in the presence of various distributed file systems even >set-UID "root" may not be enough; both NFS and RFS servers may map the >root user-ID to some unprivileged user ID. Just to chime in: In such environments, set-UID "root" programs have less priviledge than the programs that call them. I just use Doug Gwyn's getpwd() implementation. It saves me a lot of time and trouble. -- Chip Salzenberg at Teltronics/TCT <chip@tct.uucp>, <uunet!pdn!tct!chip> "If Usenet exists, then what is its mailing address?" -- me "c/o The Daily Planet, Metropolis." -- Jeff Daiell