4

I have a build system tool that is using getcwd() to get the current working directory. That's great, except that sometimes people have spaces in their paths, which isn't supported by the build system. You'd think that you could just make a symbolic link:

ln -s "Directory With Spaces" DirectoryWithoutSpaces

And then be happy. But unfortunately for me, getcwd() resolves all the symbolic links. I tried to use getenv("PWD"), but it is not pointing at the same path as I get back from getcwd(). I blame make -C for not updating the environment variable, I think. Right now, getcwd() gives me back a path like this:

/Users/carl/Directory With Spaces/Some/Other/Directories

And getenv("PWD") gives me:

/Users/carl/DirectoryWithoutSpaces

So - is there any function like getcwd() that doesn't resolve the symbolic links?

Edit:

I changed

make -C Some/Other/Directories

to

cd Some/Other/Directories ; make

And then getenv("PWD") works.. If there's no other solution, I can use that.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • what part of your program doesn't work as a result of their being spaces in a path? – eruciform Jul 17 '10 at 00:56
  • 1
    `mv ~/"Directory With Spaces" ~/DirectoryWithoutSpaces`? :P – muhmuhten Jul 17 '10 at 01:08
  • 1
    @eruciform, the tool in question generates a bunch of makefiles; for lots of reasons it chokes if there are spaces in this pathname. I've made the changes mentioned in my edit, and I'm now fixing the spaces problem as a whole, but regardless of that, it's a bit weird to generate the makefiles with a mishmash of symlinks and resolved path names. The edit I have above fixes that, but I'm still interested in alternative solutions. – Carl Norum Jul 17 '10 at 01:18
  • 4
    @eruciform, upon further investigation, fixing all of this junk to work with spaces is never going to happen. The right solution will be to remove the absolute path requirements, rather than trying to make spaces work. – Carl Norum Jul 17 '10 at 01:57

2 Answers2

6

According to the Advanced Programming in the UNIX Environment bible by Stevens, p.112:

Since the kernel must maintain knowledge of the current working directory, we should be able to fetch its current value. Unfortunately, all the kernel maintains for each process is the i-node number and device identification for the current working directory. The kernel does not maintain the full pathname of the directory.

Sorry, looks like you do need to work around this in another way.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
eruciform
  • 7,680
  • 1
  • 35
  • 47
3

There is no way for getcwd() to determine the path you followed via symbolic links. The basic implementation of getcwd() stats the current directory '.', and then opens the parent directory '..' and scans the entries until it finds the directory name with the same inode number as '.' has. It then repeats the process upwards until it finds the root directory, at which point it has the full path. At no point does it ever traverse a symbolic link. So the goal of having getcwd() calculate the path followed via symlinks is impossible, whether it is implemented as a system call or as a library function.

The best resolution is to ensure that the build system handles path names containing spaces. That means quoting pathnames passed through the shell. C programs don't care about the spaces in the name; it is only when a program like the shell interprets the strings that you run into problems. (Compilers implemented as shell scripts that run pre-processors often have problems with pathnames that contain spaces - speaking from experience.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Yes - clearly `getcwd()` won't work. I was hoping to find an alternative that would - my edit shows one. Making the build system handle spaces is a total nightmare - GNU make is notoriously bad at handling them. I think taking the absolute pathing requirements out will be easier, but still no picnic. – Carl Norum Jul 17 '10 at 05:01