Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Jul 2001 14:21:54 -0700
From:      Pat Dirks <pwd@apple.com>
To:        Paul Schenkeveld <paul@psconsult.nl>, Bakul Shah <bakul@bitblocks.com>
Cc:        <freebsd-fs@freebsd.org>, <freebsd-hackers@freebsd.org>
Subject:   Re: flags on symlinks
Message-ID:  <B7887B02.332A%pwd@apple.com>
In-Reply-To: <20010728171214.A52461@psconsult.nl>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,

Funny you should mention such a call.  When we were faced with supporting
access to get and set all the various file attributes that Mac OS supports
on HFS/HFS+ volumes in Apple's Mac OS X kernel we decided to implement two
new system calls:

    int getattrlist (const char* path,
                     void* attrlist,
                     void *buffer,
                     size_t length,
                     unsigned long options);
And

    int setattrlist ( ... );  [same arguments]

Where "attrlist" is a pointer to a block of flags 5 longwords of flags
(separate flags for directory, file, and common information, for instance),
buffer/length specify a block of attribute information to be filled in (in
the case of getattrlist) or set (in the case of setattrlist), and "options"
allows for the specification of options such as FSOPT_NOFOLLOW, which
specify operation on a symlink ITSELF rather than following it.

The semantics are very much along the lines you envision, except that the
information is packed into a separate buffer whose size is determined by the
attribute information being passed.

It's worked out to be a very flexible mechanism for getting attribute
information in and out of the system.  We've expanded the list of defined
attributes since it was first implemented with good success (there's no need
to redefine the buffer structure being passed, so binary compatibility has
been no problem).

If you're curious about the implementation, have a look at the Darwin
sources, or drop me a line.

Cheers,
-Pat Dirks
Mac OS X Filesystems Tech Lead.

On 7/28/01 8:12 AM, "Paul Schenkeveld" <paul@psconsult.nl> wrote:

> Guys,
> 
> Don't know if this is too far off from the current UN*X we know but
> I never understood why we don't have the following one (and last as
> far as manipulating inodes is concerned) new system call:
> 
>   int chstat(ulong_t *flags, union ch_target target,
>       struct stat *change);
> 
> Flags tells what we would like to change and is a combination of the
> following:
> 
>   #define CH_OWN    0x00000001
>   #define CH_GRP    0x00000002
>   #define CH_MOD    0x00000004
>   #define CH_FLAGS    0x00000008
>   #define CH_ATIME    0x00000010
>   #define CH_MTIME    0x00000020
>   #define CH_CTIME    0x00000040    /* perhaps not this one... */
>   #define CH_SIZE    0x00000080
> 
>   #define CH_FD    0x20000000
>   #define CH_PATH    0x40000000
>   #define CH_SELF    0x80000000    /* to not follow a final symlink */
> 
> When chstat returns an error, bits in *flags can indicate what
> changes caused the problem.  Perhaps an extra flag CH_ATOMIC could
> be added to request an all-or-nothing operation.
> 
> The flags approach also allows us to add optional arguments in the
> future.  So maybe we could even have something like this, requiring
> an optional fourth argument char *ltarget to the chstat system call:
> 
>   #define CH_LTARG    0x00000100    /* to atomically change the */
> /* target of a symbolic link */
> 
>   int chstat(ulong_t *flags, union ch_target target,
>       struct stat *change, char *ltarget);
> 
> The union target specifies how we address the inode, by name, file
> descriptor or whatever we may want to think of.
> 
>   union ch_target {
> char *path;
> int fd;
> ...        /* who knows what else in the future */
>   };
> 
> The (struct stat *) change points at the
> 
>   /*
>   ** the system call itself, the int contains CH_* flags,
>   ** the union addresses the target inode by name or filedescriptor
>   ** and of the struct stat those members will be taken that are
>   ** addressed by the bitmask
>   */
> 
> This could eventually replace [fl]chown, [fl]chmod, [f]chflags,
> [fl]utimes and [f]truncate (hope I did not forget some) system
> calls which could be emulated by library functions.
> 
> We don't need to open an inode if we don't want to and making the
> chstat() call available to applications could speed up such programs
> as cp, mv, tar, cpio, pax and restore when they are able to combine
> multiple changes into one system call.
> 
> The argument flags could also be
> 
> If I'm running too fast, please forgive me and ignore this message
> but the discussion about adding more system calls becoming a problem
> made me feel this is the right time to share my thoughts on this.
> 
> Regards,
> 
> Paul Schenkeveld, Consultant
> PSconsult ICT Services BV
> 
> On Sun, Jul 22, 2001 at 05:16:11PM -0700, Bakul Shah wrote:
>>>> I guess there is general agreement that it is desirable to be able to set
>>>> schg,sunlink etc on symlinks and fifos.
>> 
>>> Probably devices, too, which is a can of worms, particularly
>>> with devfs.
>> 
>>> Already, the fchown/fchmod on sockets and other things which
>>> use a non VFS struct fileops fails -- I think this includes
>>> FIFO's.
>> 
>>>> The consistency argument goes like this:
>>>> 
>>>> Currently exposed as accessor methods to VOP_SETATTR are:
>>>> chmod(2), fchmod(2), lchmod(2)
>>>> chown(2), fchown(2), lchown(2)
>>>> chflags(2), fchflags(2)
>>> 
>>> I know the argument for adding more and more system calls;
>>> I just don't agree with it.  BSDI has already suggested
>>> limiting the total number of FreeBSD system calls to something
>>> like less than 32 more, total, without going to another block
>>> much higher up, and having to have FreeBSD allocate a large,
>>> sparse system call array, adding potentially a lot of overhead,
>>> depending on future directions with the ABI.
>> 
>> Well, I won't mind if {,l}ch{mod,own,flags} etc become library
>> routines.  Something like:
>> 
>> int
>> chown(const char* path, uid_t owner, gid_t group) {
>> int fd, err;
>> 
>> fd = open(path, O_EXCL);
>> if (!fd)
>> return errno;
>> err = fchown(fd, owner, group);
>> close(fd);
>> return err;
>> }
>> 
>> But then you must be able to open() a symlink (O_NOFOLLOW
>> flag must not make the open fail).
>> 
>> My main argument is for consistent treatment and for `equal
>> rights': if an object has an inode it must have the same
>> rights as any other object also with an inode.  devfs is a
>> different kind of beast just like msdosfs so rights of an
>> inode based object are not the same as rights of devfs or
>> msdos fs.  Anyway, I argue for either adding a syscall or
>> deleting a few to make a consistent set!
>> 
>> Earlier you said:
>>> If the chflags call was defined to always affect its
>>> target (and not follow links), then the user space utility
>>> could do the stat/readlink itself, and find the correct
>>> target, if it wasn't told to not follow links.
>> 
>> I don't like running namei twice.  Between the stat/readlink
>> and chflags(), things can change.
>> 
>> [Digressing a bit...]
>> Ideally I want only the f* version of syscalls, so that you
>> _have_ to `open' an object.  Open gives you a handle, a
>> 'capability' to operate on the object.  In the past I have
>> argued for *always* passing in a capability even for open().
>> Then you can throw away even the chdir() call.  But then
>> it won't be the unix we know and love and hate!
>> 
>> -- bakul
>> 
>> To Unsubscribe: send mail to majordomo@FreeBSD.org
>> with "unsubscribe freebsd-fs" in the body of the message
> 
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-fs" in the body of the message
> 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?B7887B02.332A%pwd>