[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: mkdir when target exists and is a broken symlink
From: |
Eric Blake |
Subject: |
Re: mkdir when target exists and is a broken symlink |
Date: |
Tue, 17 May 2005 22:04:04 +0000 |
> ln -s nonexistent foo
> There could be some kind of -f, --follow option so that mkdir will
> create the directory pointed to. You'd probably use it together with
> -p. Then 'mkdir -fp' would be a way to try everything sensible to make
> sure the destination exists and can be used as a directory (ie, is a
> directory itself or a symlink to one).
This sounds somewhat similar to cp -f, --force. cp uses slightly different
semantics, required by POSIX (rather than try to create the new file at the
location specified by the dangling symlink, it unlinks the symlink and creates
the new file in its place). I would lean more toward force semantics than
follow semantics if `mkdir -fp' were supported. In particular, how would
follow semantics behave with `mkdir -fp circular'?
> I note that 'touch foo' when foo is a broken symlink will create the
> link destination if possible
Hmm, you may have unconvered a POSIX bug or coreutils compliance bug:
POSIX requires that touch do the equivalent of calling creat() if the file does
not exist, then call utime() whether or not creat() was called. A broken
symlink exists, so step one should be skipped, then in step two, utime() should
fail with ENOENT when trying to resolve the (still) broken symlink. But
coreutils is using open(O_CREAT) as the simultaneous check for existance and
replacement call for creat(). Normally, this is identical, but in the case of
a broken symlink, it is not (remember, POSIX states that open("foo",
O_CREAT|O_EXCL) must fail with EEXIST; but without O_EXCL, it follows the link
as if open("nonexistent", O_CREAT) had been called, thus creating the target).
Then in step two, since nonexistent now exists, futimens (coreutils much nicer
replacement for utime) is successfully changing nonexistent's time. This may
be an unintentional oversight in POSIX, worthy of bringing before the Austin
group, because the semantics of touch populating a previously dangling symlink
are useful.
Furthermore, create() is equal to open(O_WRONLY|O_CREAT|O_TRUNC), but coreutils
is using open(O_WRONLY|O_CREAT|O_NONBLOCK|O_NOCTTY). The omission of O_TRUNC
is okay (it has no semantics when the file did not exist, touch should only
create the file if it did not exist, and checking for existance with O_TRUNC is
destructive). But the addition of O_NONBLOCK and O_NOCTTY, while reasonable,
are not allowed by the strict reading.
Finally, a related feature request: on systems that support lutime() and family
(and where lstat() provides meaningful times on the symlink), touch should
probably support -L,--logical and -P,--physical to control whether the time
being touched is of the actual symlink or of its target.
--
Eric Blake