[comp.sys.amiga.programmer] Checking to see if a file's a link

davids@ucscb.ucsc.edu (Dave Schreiber) (04/29/91)

Is there a way, under 2.0, to examine a file or directory from a program
and determine whether or not it's a link?  I'm trying to write a DU program
that will avoid going in circles if there's a link in a directory to an
ancestor of that directory.

On a related topic, will the release version of Workbench 2.x have this
sort of protection built into it's recursive commands (like dir)?  Currently,
if I have a directory 'foo', with a link to it's parent directory, and I
do a 'dir foo all', dir ends up going in circles.

Thanks.

-- 
Dave Schreiber                                    davids@ucscf.ucsc.edu 
"It was fun learning about logic, but I don't see where or when I will ever
use it again."

jap@convex.cl.msu.edu (Joe Porkka) (04/29/91)

davids@ucscb.ucsc.edu (Dave Schreiber) writes:



>Is there a way, under 2.0, to examine a file or directory from a program
>and determine whether or not it's a link?  I'm trying to write a DU program
>that will avoid going in circles if there's a link in a directory to an
>ancestor of that directory.

Yeah, you gotta check the fib_FileType for specific values.
I don't remember what the values are offhand, but its easy to find
my making a simple program to Examine("afile") and print the
resulting fib struct, then test it out on links and regular files.

BTW, 1.3 can't tell the diff between a link and a real file, but
it does not actually follow links. (Ie, file links and dir links are empty)

>On a related topic, will the release version of Workbench 2.x have this
>sort of protection built into it's recursive commands (like dir)?  Currently,
>if I have a directory 'foo', with a link to it's parent directory, and I
>do a 'dir foo all', dir ends up going in circles.


Hopefully. Currently it don't.

johno@cbmvax.commodore.com (John Orr - CATS) (04/29/91)

In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:
>
>
>Is there a way, under 2.0, to examine a file or directory from a program
>and determine whether or not it's a link?


from <dos/dosextens.h>:

/* Types for fib_DirEntryType.  NOTE that both USERDIR and ROOT are      */
/* directories, and that directory/file checks should use <0 and >=0.    */
/* This is not necessarily exhaustive!  Some handlers may use other      */
/* values as needed, though <0 and >=0 should remain as supported as     */
/* possible.                                                             */
#define ST_ROOT         1
#define ST_USERDIR      2
#define ST_SOFTLINK     3       /* looks like dir, but may point to a file! */
#define ST_LINKDIR      4       /* hard link to dir */
#define ST_FILE         -3      /* must be negative for FIB! */
#define ST_LINKFILE     -4      /* hard link to file */


If you are using Examine() and ExNext() to do your directory scanning,
just compare the FileInfoBlock's fib_DirEntryType field to the above
#defines.


--John

markv@kuhub.cc.ukans.edu (04/29/91)

In article <MWM.91Apr29120935@raven.pa.dec.com>, mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
> In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:
>   Is there a way, under 2.0, to examine a file or directory from a program
>   and determine whether or not it's a link?  I'm trying to write a DU program
>   that will avoid going in circles if there's a link in a directory to an
>   ancestor of that directory.
> 
> Yeah - check DirEntryType (or whatever you check to see if it's a
> directory)....
>    On a related topic, will the release version of Workbench 2.x have this
>    sort of protection built into it's recursive commands (like dir)? 
>    Currently, if I have a directory 'foo', with a link to it's parent
>    directory, and I do a 'dir foo all', dir ends up going in circles.
> 
> Last time I reported this bug, I was told that they were going to
> "fix" the problem by having makelink not allow circular links.

I think the latest 2.0 Makelink will still do make circular links.
There is a better solution.

2.0 dos.library has a function called SameLock() that takes two locks
and returns TRUE if they are the same object (I think all it does is
check for a match of the handler and header block fields).  With this,
just keep a Lock on each level of the tree you've walked down, and if
you step into a link, then check for a match with each parent.  If
you get a match, you've made a cycle and skip that link, otherwise,
you can proceed with that link safely.

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark Gooderum			Only...		\    Good Cheer !!!
Academic Computing Services	       ///	  \___________________________
University of Kansas		     ///  /|         __    _
Bix:	  mgooderum	      \\\  ///  /__| |\/| | | _   /_\  makes it
Bitnet:   MARKV@UKANVAX		\/\/  /    | |  | | |__| /   \ possible...
Internet: markv@kuhub.cc.ukans.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (04/30/91)

In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:
   Is there a way, under 2.0, to examine a file or directory from a program
   and determine whether or not it's a link?  I'm trying to write a DU program
   that will avoid going in circles if there's a link in a directory to an
   ancestor of that directory.

Yeah - check DirEntryType (or whatever you check to see if it's a
directory). If the absolute value is 4, it's a link. This data is from
my faulty memory, so you should build a link and check the value.
I am sure that it's a single absolute value, though.

   On a related topic, will the release version of Workbench 2.x have this
   sort of protection built into it's recursive commands (like dir)? 
   Currently, if I have a directory 'foo', with a link to it's parent
   directory, and I do a 'dir foo all', dir ends up going in circles.

Last time I reported this bug, I was told that they were going to
"fix" the problem by having makelink not allow circular links. That
this implied searching the entire subtree beneath the link didn't seem
to bother the person who posted that fix.

	Bleah,
	<mike
--
Here's a song about absolutely nothing.			Mike Meyer
It's not about me, not about anyone else,		mwm@pa.dec.com
Not about love, not about being young.			decwrl!mwm
Not about anything else, either.

davids@ucscf.UCSC.EDU (Dave Schreiber) (04/30/91)

In article <21041@cbmvax.commodore.com> johno@cbmvax.commodore.com (John Orr - CATS) writes:
>In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:

>>Is there a way, under 2.0, to examine a file or directory from a program
>>and determine whether or not it's a link?

>from <dos/dosextens.h>:

[list of needed #DEFINEs deleted]

Thanks.  Unfortunatly, my copy of dos/dosextens.h didn't come with these
#DEFINEs (Rev. 36.24: 90/07/12;  I got it with SAS/C V5.10).

>--John


-- 
Dave Schreiber                               E-mail:  davids@ucscf.ucsc.edu
"It was fun learning about logic, but I don't see where or when I will ever
use it again."                               Disclaimer:

ccplumb@rose.waterloo.edu (Colin Plumb) (04/30/91)

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) wrote:
> Last time I reported this bug, I was told that they were going to
> "fix" the problem by having makelink not allow circular links. That
> this implied searching the entire subtree beneath the link didn't seem
> to bother the person who posted that fix.

You have to do this on rename, anyway, to avoid the Ouroboros bug.
(Under 1.3, on a scratch floppy, makedir foo; makedir foo/bar;
rename foo foo/bar/foo;  *Poof*.)  Actually, to check for this, you
don't search the entire subtree under the source; rather you check
all parents of the destination.  To check that a proposed link
to foo: with name bar:foo isn't circular, check that bar:, bar:/, bar://,
etc. are not the same as foo:.  Given SameLock(), it's trivial to
write.

(Question: under AmigaDOS 2.0, it seems that a file or directory is
distinguishable from a hard link to it.  If this is so, obviously
my Unix understanding of hard links is invalid.  What exactly are
the semantics of one?  Are they low-level pointers, and can one remove
the file pointed to?  How does the FS ensure the dangling link isn't
picked up?)
-- 
	-Colin

mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) (05/01/91)

In article <1991Apr30.070121.24535@watdragon.waterloo.edu> ccplumb@rose.waterloo.edu (Colin Plumb) writes:
   mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) wrote:
   > Last time I reported this bug, I was told that they were going to
   > "fix" the problem by having makelink not allow circular links. That
   > this implied searching the entire subtree beneath the link didn't seem
   > to bother the person who posted that fix.

   You have to do this on rename, anyway, to avoid the Ouroboros bug.
   (Under 1.3, on a scratch floppy, makedir foo; makedir foo/bar;
   rename foo foo/bar/foo;  *Poof*.)  Actually, to check for this, you
   don't search the entire subtree under the source; rather you check
   all parents of the destination.  To check that a proposed link
   to foo: with name bar:foo isn't circular, check that bar:, bar:/, bar://,
   etc. are not the same as foo:.  Given SameLock(), it's trivial to
   write.

Nope, just checking parents of the destination isn't good enough. If
there is a link to a parent of the destination somewhere under the
source, then a recursive descent of the source will follow the old
link to that parent, down to the destination, and back to the source
via the new link.  Checking the parents only finds things that are
directly circular; it doesn't find things that are indirectly
circular. I.e, if foo:bar is a link to bar, then your test won't
notice that foo:bar/foo is the same as foo: (and bar:foo/bar is the
same as bar:).

Unix solved this in two different ways for the two different kinds of
links. Applications don't walk soft links unless they are explicitly
told to. You can guard against loops (if you want to) by keeping a
list of the soft links you've walked. The ln command won't (normally)
let you create a hard link to a directory, so there can't be any
circular links with hard links.

	<mike
--
I know the world is flat.				Mike Meyer
Don't try tell me that it's round.			mwm@pa.dec.com
I know the world stands still.				decwrl!mwm
Don't try to make it turn around.

umueller@iiic.ethz.ch (Urban Dominik Mueller) (05/02/91)

>2.0 dos.library has a function called SameLock() that takes two locks
>and returns TRUE if they are the same object (I think all it does is
>check for a match of the handler and header block fields).  With this,
>just keep a Lock on each level of the tree you've walked down, and if
>you step into a link, then check for a match with each parent.  If
>you get a match, you've made a cycle and skip that link, otherwise,
>you can proceed with that link safely.

>Mark Gooderum			Only...		\    Good Cheer !!!
>[huge .sig deleted]

Nice idea, really. But it has its drawbacks, too. Remember the original
question: Somebody wanted to create a 'du' type utility. Now if there
is a link that points downward in the directory tree, the contents
of that link (directory or file) will be counted twice. CSH has a 
built in 'du' like feature ('dir -v'), and there I have decided not to
look at links at all. Comments?
BTW: How fast is SameLock()?

 -U. Dominik Mueller      umueller@iiic.ethz.ch       .sig light!

jay@deepthot.cary.nc.us (Jay Denebeim) (05/02/91)

In article <1991Apr29.160901.30173@kuhub.cc.ukans.edu> markv@kuhub.cc.ukans.edu writes:
>In article <MWM.91Apr29120935@raven.pa.dec.com>, mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
>> In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:
>> 
>>    On a related topic, will the release version of Workbench 2.x have this
>>    sort of protection built into it's recursive commands (like dir)? 
>>    Currently, if I have a directory 'foo', with a link to it's parent
>>    directory, and I do a 'dir foo all', dir ends up going in circles.

Its fixed in all the commands now.  
>> 
>2.0 dos.library has a function called SameLock() that takes two locks
>and returns TRUE if they are the same object (I think all it does is
>check for a match of the handler and header block fields).  With this,
>just keep a Lock on each level of the tree you've walked down, and if
>you step into a link, then check for a match with each parent.  If
>you get a match, you've made a cycle and skip that link, otherwise,
>you can proceed with that link safely.

This is what we did.  Its a little more complicated than that, but
that's close.

--

 |_o_o|\\
 |. o.| || The           Jay Denebeim
 | .  | ||  Software
 | o  | ||   Distillery
 |    |//        Address: UUCP:     mcnc.org!deepthot.uucp!jay
 ======                   Internet: jay@deepthot.cary.nc.us
                 BBS:(919)-460-7430      VOICE:(919)-460-6934

markv@kuhub.cc.ukans.edu (05/13/91)

>>2.0 dos.library has a function called SameLock() that takes two locks
>>and returns TRUE if they are the same object... If
>>you get a match, you've made a cycle and skip that link, otherwise,
>>you can proceed with that link safely.
> 
>>Mark Gooderum			Only...		\    Good Cheer !!!
> 
> Nice idea, really. But it has its drawbacks, too...

True.  I wasn't trying to avoid doing the same dir twice, only
avoiding looping.  At least you then know a 'DIR ALL' type command
will eventually complete.  Whether to actually step into a link is a
semantic issue.  I have played around a bit (writing a better search
for a file program), and decided to go with the default of following
hard links and ignoring soft links.
-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mark Gooderum			Only...		\    Good Cheer !!!
Academic Computing Services	       ///	  \___________________________
University of Kansas		     ///  /|         __    _
Bix:	  mgooderum	      \\\  ///  /__| |\/| | | _   /_\  makes it
Bitnet:   MARKV@UKANVAX		\/\/  /    | |  | | |__| /   \ possible...
Internet: markv@kuhub.cc.ukans.edu
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

jesup@cbmvax.commodore.com (Randell Jesup) (05/14/91)

In article <MWM.91Apr29120935@raven.pa.dec.com> mwm@pa.dec.com (Mike (My Watch Has Windows) Meyer) writes:
>Yeah - check DirEntryType (or whatever you check to see if it's a
>directory). If the absolute value is 4, it's a link. This data is from
>my faulty memory, so you should build a link and check the value.
>I am sure that it's a single absolute value, though.

	See the values posted here earlier (hard links to dirs and files have
different values).

	Note: you can ONLY check for this if you examine the directory it's in
and get to it via ExNext (or use ExAll()).  Once you've locked it, it has no
idea how you got to the object anymore (and ParentDir may not take you where
your think!)  Ditto for Open(), etc.

>   On a related topic, will the release version of Workbench 2.x have this
>   sort of protection built into it's recursive commands (like dir)? 
>   Currently, if I have a directory 'foo', with a link to it's parent
>   directory, and I do a 'dir foo all', dir ends up going in circles.
>
>Last time I reported this bug, I was told that they were going to
>"fix" the problem by having makelink not allow circular links. That
>this implied searching the entire subtree beneath the link didn't seem
>to bother the person who posted that fix.

	Well, that fix is still in (with an override).  For 2.04 release,
there's also protection against ILooped hardlinks in MatchNext - it refuses
to actually enter hardlinked dirs when doing an "ALL" operation (they appear
empty).  This can be over-ridden via an "I really know what I'm doing" bit.
This does not protect you if you roll your own "ALL" via ExNext/Lock/etc, or
when running 1.3 commands (which don't use MatchNext).

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
Thus spake the Master Ninjei: "To program a million-line operating system
is easy, to change a man's temperament is more difficult."
(From "The Zen of Programming")  ;-)

jesup@cbmvax.commodore.com (Randell Jesup) (05/14/91)

In article <1991Apr30.070121.24535@watdragon.waterloo.edu> ccplumb@rose.waterloo.edu (Colin Plumb) writes:
>(Question: under AmigaDOS 2.0, it seems that a file or directory is
>distinguishable from a hard link to it.  If this is so, obviously
>my Unix understanding of hard links is invalid.  What exactly are
>the semantics of one?  Are they low-level pointers, and can one remove
>the file pointed to?  How does the FS ensure the dangling link isn't
>picked up?)

	They're not quite indistinguishable.  You can detect them in a
directory (via ST_LINKDIR, etc).  If you lock something, you can find out if
the thing (or rather last portion of the path) was a link by checking both
Examine against the filename portion of the path, and ParentDir against what
"should" be the parentdir (lock on the PathPart of the path).  In most ways
they're indistinguishable, though, just not quite as much as Unix (because
of the difference between an inode setup and the way things are linked in 
the Amiga FS.)

	If the "real" file is deleted (the one that NameFromLock(Lock(...)...)
gives you), the next link in the chain becomes the "real" file.  When the
last link is deleted, the file disappears.

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is anything other than my personal opinion.
Thus spake the Master Ninjei: "To program a million-line operating system
is easy, to change a man's temperament is more difficult."
(From "The Zen of Programming")  ;-)

sjk@aura.nbn.com (Scott J. Kramer) (05/23/91)

In article <15127@darkstar.ucsc.edu> davids@ucscb.ucsc.edu (Dave Schreiber) writes:

   From: davids@ucscb.ucsc.edu (Dave Schreiber)
   Newsgroups: comp.sys.amiga.programmer
   Date: 28 Apr 91 20:56:13 GMT
   Sender: usenet@darkstar.ucsc.edu
   Organization: University of California, Santa Cruz; Open Access Computing


   Is there a way, under 2.0, to examine a file or directory from a program
   and determine whether or not it's a link?  I'm trying to write a DU program
   that will avoid going in circles if there's a link in a directory to an
   ancestor of that directory.

And is using `which' the only way to determine this from the shell?

Here's a potentially-dangerous scenario with hard links to
directories:

    shell> version
    Kickstart version 36.207. Workbench version 36.69
    shell> makedir xxx
    shell> echo > xxx/a foo
    shell> echo > xxx/b baz
    shell> makelink zzz xxx
    shell> which xxx
    Ram Disk:xxx
    shell> which zzz
    shell> list zzz
    Ram Disk:xxx
    Directory "Ram Disk:xxx" on Wednesday 22-May-91
    b                              4 ----rwed Today     15:44:44
    a                              4 ----rwed Today     15:44:41
    2 files - 4 blocks used
    shell> delete xxx all
    Ram Disk:xxx/b  Deleted
    Ram Disk:xxx/a  Deleted
    Ram Disk:xxx  Deleted
    shell> which zzz
    Ram Disk:x
    H/pGDone

Seems too easy to clobber a directory that has links to it.  Under
UNIX, you can remove a file/directory which has *symlinks* to it and
at least have a pointer, even if to a non-existent object.

I don't think hard links to directories are a good idea.
--

Scott J. Kramer			UUCP:	   {sun,ucbvax}!pixar!aura!sjk
P.O. Box 3392			Internet:  sjk@aura.nbn.com
San Rafael, CA  94912