Re: chmod, chgrp and symlinks

From: Kasper Dupont (kasperd@daimi.au.dk)
Date: 02/06/03


From: Kasper Dupont <kasperd@daimi.au.dk>
Date: Thu, 06 Feb 2003 11:39:55 +0100

Ramazan Jah-Far wrote:
>
> About original poster's script:
> * he has files under "/usr/space/mp3" and wants to
> apply some policy to all files of this class;
> * programmatically he cannot easily detect complete
> "set of classes" for a file inside /usr/space/mp3;
> * he _may not_ make decisions based upon incomplete
> "class set" of a file object.

Since he is going to scan the entire tree, he could
know if all hardlinks are inside that tree. But of
course finding the rest of the hardlinks does require
a scan of the entire filesystem.

>
> KD> But if it really is that necesarry, the directory could
> KD> be made on a separate filesystem.
>
> Yes. It's even possible to create filesystem inside
> a file just to avoid repartitioning harddisk.

Sure, not as efficient as a partition, but much more
convenient.

>
> KD> In some cases it would be nice to prevent hardlinks even
> KD> between subtrees of the same filesystem, in particular
>
> BTW, hardlinks to directories are impossible.
> I think you know *why*.

One fundamental problem about hardlinks to directories
is: where should .. point? Another problem is removing,
usually a directory must be empty to be removed. But
in case of links it is different. (I remember once on
AmigaOS using a program without knowing enough about
symlinks to remove a symlink to a directory. The program
started removing every file from the directory before
removing the symlink. Damn.) With hardlinks to directories
it becomes more difficult, you can remove all hardlinks
but one without emptying the directory. The link count on
the directory does not tell you if there are other links,
because subdirectories has .. links to the directory.
(Which we don't know where to point anyway.) But in a few
cases we could not remove a link to a directory even if
there were more links, because doing so would make the
directory structure disconnected. (In a buggy OS that
could happen even without hardlinks to directories if you
allow to move a directory into itself, that could be done
by a single process or a race condition between multiple
directory movings.)

>
> KD> in combination with directory quotas.
>
> 1) IMO it would be _the best_ to eliminate hardlinks
> from linux scene. Completely.

No way. Do you have any idea how much you would break
by disallowing hardlinks?

> 2) Do you really want to add this complexity (hardlinks
> permissions/quotas) to linux filesystem?

Yes. It doesn't have to be that complicated. Hardlinks
and permissions are quite simple, so are user quotas.
Directory quotas would in many cases be more convenient
than user quotes, but they are complicated in the
presence of hardlinks. Thus I would disallow anybody but
root to make hardlinks in directories under different
quotas. The problem is, that no matter how you account
for hardlinked files, you will run into trouble. Consider
the following scenario, that will always cause trouble.

/home/user1 has a 1GB quota
/home/user2 has a 100MB quota

- user1 creates a 1MB file in /home/user1, obviously
  this should be allowed.
- user2 creates a hardlink of that file in /home/user2,
  we are still far from the quota, but could refuse the
  hardlink as if /home/user1 and /home/user2 were on
  different filesystems.
- user1 appends to the file until it is 200MB in size.
- user1 deletes the file. Now there is a 200MB file in
  /home/user2 which cannot be accounted for.

The only of the above steps that you could with any
reason refuse is the linking. But eventhough the file
cannot be linked between directories with different
quota, it should still be allowed to move the file to
a directory under a different quota, because otherwise
we would have to do an inefficient copy and remove
process.

Now comes of course the problem of moving a file with
multiple links between quotas. Or moving a directory
between quotas. Can anybody define, what is the right
behaviour? And what datastructures will allow the
decissions to be made efficiently?

A file simultaneously existing under different quotas
can lead to overuse of one quota, and thus only root
should be allowed to create such a thing.

> IMO it's
> better to keep things simple and elegant instead of
> complex and monstrous :-)

As for filesystems I want simplicity and elegance in
the API, but the underlying filesystem may be complex
if that is necesarry to make an efficient and correct
implementation. None of my suggestions will make a
complex API, but the underlying filesystem might need
some complicated structures.

>
> P.S.
> I'd like to know what is a point of using hardlinks
> instead of symlinks?

For example atomic replacing an old file with a new
would temporarily create a hardlink. It could look
like this:

create("filename.new");
link("filename","filename.old");
rename("filename.new","filename");

A similar approach is often used when creating lock
files.

It is also convenient if one instance of a file is
in a directory not accessible for everybody. A
symlink would not give access to the file for anybody
who couldn't already access it, but a hardlink would
work if you want to let other people have access to
the file.

There is a major difference between using hardlinks
and symlinks in case the original is removed. If the
original is removed in case of a hardlink other
hardlinks will still work. Had it been a symlink it
would now be a dangling link.

RedHat has used hardlinks for some of the files
installed by RPM in cases where a lot of identical
files were used, in there were no essential
difference justifying the choice to make one the
"original" which others points to.

Hardlinks are convenient for some kinds of versioned
backup, where a lot of files have not been changed
between two backups. If this was done with symlinks,
a restore with cp -a would not work.

There are probably a lot more uses of hardlinks which
I do not remember right now.

-- 
Kasper Dupont -- der bruger for meget tid på usenet.
For sending spam use mailto:aaarep@daimi.au.dk
for(_=52;_;(_%5)||(_/=5),(_%5)&&(_-=2))putchar(_);


Relevant Pages