Bug? in os.chown()
Jim Dennis
jimd at vega.starshine.org
Mon Jan 1 19:21:08 EST 2001
In article <92q08p$1doj$1 at news.cybercity.dk>, Erwin S. Andreasen wrote:
>On Sun, 31 Dec 2000 17:27:25 -0600, David Lambert wrote:
>> I am running Python 2.0 on Mandrake Linux 7.2 and have come across an
>> apparent anomaly with os.chown(). Running a process as root, I can
>> change any file's ownerships apart from symbolic links. No error is
>> given, but the ownership refuses to be changed. Is this a feature or a
>> bug? How do I change a symbolic link's owner and group?
> Just about any operation on a symbolic link (i.e. open, chdir etc. but not
> unlink) will act on the file linked to instead. So you are really changing the
> permission on the target file. (Note, however, that while the system call
> chown follows the link, the GNU chown program does NOT follow the link and
> changes the owner of the link -- at least with 4.0.35 version of fileutils).
> There are a number of l* system calls that act on the link rather than the
> thing being linked to (lstat, lchown). However, Python doesn't implement
> lchown yet (at least not in Python 2.0b1).
> So, I suppose you could use system() to run GNU chown on the file (you could
> give it the --no-dereference flag to be sure, see man 1 chown) -- it's only
> necessary to do it when the target is a symbolic link (you can check using
> os.path.islink). Not a very portable solution though.
Looking at my O'Reilly/Lutz Pocket Reference I see that there is a
readlink() method somewhere under the os module. It wasn't clear
whether they meant os.readlink() or os.path.readlink() (from the
text of the book). I've figured out that os.readlink() works.
It appears that os.readlink() only follows one level of linkage.
(I tested this by preparing a simple set of symlinks using:
cd tmp && touch foo && ln -s foo lfoo; ln -s lfoo llfoo
ln -s llfoo lllfoo
and then interactively importing os and playing with it; duh).
So I guess you need to do something like:
fname="./lllfoo"
while os.path.islink(fname):
fname=os.readlink(fname)
(which works for my test case, though I notice that it
stripped the leading ./ from my name; I guess it does some
sort of path canonicalization).
... is there a better way? Is there a "readlinks()" method
that automates this process? Does this throw an exception
if the link is dangling, or if it is circular, or if it
"might" be circular because it exceeds some maximum? Should
I wrap os.readlink() in a try: except:? What are the exceptions
that os.readlink() can throw? What are the exceptions that
os.path.islink() could throw? (ENOENT, and EPERM seem like
obvious OS errors; but I know know how to find the Python
exception names that correspond to these system errors).
More information about the Python-list
mailing list