Bug 209593 - [api] Add support for "file permissions" and "owner" properties for unix files
Summary: [api] Add support for "file permissions" and "owner" properties for unix files
Status: RESOLVED FIXED
Alias: None
Product: Target Management
Classification: Tools
Component: RSE (show other bugs)
Version: 3.0   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.0 M5   Edit
Assignee: David McKnight CLA
QA Contact: Martin Oberhuber CLA
URL:
Whiteboard:
Keywords: api
Depends on:
Blocks: 165171 180507 218040 218042
  Show dependency tree
 
Reported: 2007-11-12 22:54 EST by Ankit Pasricha CLA
Modified: 2008-02-13 15:58 EST (History)
3 users (show)

See Also:


Attachments
potential service interfaces permissions and ownership (8.66 KB, patch)
2008-01-10 09:32 EST, David McKnight CLA
no flags Details | Diff
updated patch of potential service inferfaces permissions and ownership (8.62 KB, patch)
2008-01-10 12:54 EST, David McKnight CLA
no flags Details | Diff
next patch iteraction of potential service apis (13.07 KB, patch)
2008-01-10 14:02 EST, David McKnight CLA
no flags Details | Diff
updated patch (10.95 KB, patch)
2008-01-10 15:30 EST, David McKnight CLA
no flags Details | Diff
updated patch with dstore implementation (31.43 KB, patch)
2008-01-11 12:09 EST, David McKnight CLA
no flags Details | Diff
updated patch with property page for exercising this (55.38 KB, patch)
2008-01-11 15:10 EST, David McKnight CLA
no flags Details | Diff
patch with further evolution of the enhancement (85.29 KB, patch)
2008-01-15 12:52 EST, David McKnight CLA
no flags Details | Diff
patch to consolidate permissions and initial get support for ftp and ssh (82.80 KB, patch)
2008-01-21 13:29 EST, David McKnight CLA
no flags Details | Diff
updated patch with suggestions from martin (82.76 KB, patch)
2008-01-22 13:35 EST, David McKnight CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ankit Pasricha CLA 2007-11-12 22:54:28 EST
For unix-like files, I would like to see "file permissions" and "owner" properties added. This support should be added to:

1. Info Property page and Properties sheet: I should be able to view file permissions and change them (i.e. 'chmod' functionality). I should also be able to view the owner of the file and modify that property ('chown' functionality).

2. Remote System Details table view: Add new columns to display this functionality.

3. Access to these properties through APIs.
Comment 1 Kevin Doyle CLA 2007-11-12 23:11:55 EST
Some related bugs:

Bug #165171 for exposing file permissions and ownership through API.
Bug #180507 for a dialog for changing file permissions.  
Comment 2 David McKnight CLA 2007-12-04 16:35:11 EST
There are a few things to consider with this one.  

1) First, whether or not all services are able to support this.  Can FTP do this?  If a service doesn't support permissions and owner properties, then we'll have to account for the differences in the UI.  

2) For dstore, this will effect compatability with older releases since we would need to store different info in DataElements and we would to workout a scheme that support the older versions as well as the newer.  

3) What commands should we use on the remote system to determine permissions and ownership.  Will different unixes have different commands or formats?

4) Another thing to consider is whether this would effect performance - for dstore, we might gather this info as part of file classification, such that the info comes back asynchronously after the initial query.

Comment 3 David McKnight CLA 2008-01-10 09:32:53 EST
Created attachment 86557 [details]
potential service interfaces permissions and ownership

I've attached a patch with potential service APIs that could be used for retrieving and modifying permissions and ownership.  

A service implementation, such as the DStoreFileService, could implement these interfaces to provide support for the permissions and ownership, while services that are unable to provide this support would not.

Dave Dykstal, suggested that we provide a mechanism to adapt to the permissions and ownership interfaces and use that to determine (1) whether these features are supported, and if so (2) the underlying service implementations.

Any thoughts, issues or questions about these interfaces?
Comment 4 Martin Oberhuber CLA 2008-01-10 09:57:27 EST
I'd also prefer adapting to the new interfaces rather than implementing them. When you do that, you'll probably need to pass the original IFileService as a parameter into the methods, such that the adaptor knows what it should adapt to.

The IHostFilePermissions interface seems like an overkill to me -- just aggregating 9 booleans can also be done with a single integer plus some bitmask constants, and is easier to extend in a binary compatible way like that. The typical UNIX ugo=rwxrwxrwx bitfield should be just fine.

I think I'd like to see canSetFilePermissions() and canSetFileOwner() methods because often the service has a chance to determine whether the call has any chance to succeed -- like if the file is owned by somebody else. Corresponding UI actions should be disabled in that case, perhaps with a tooltip telling the reason why it's disabled.
Comment 5 David McKnight CLA 2008-01-10 10:51:31 EST
(In reply to comment #4)
> The IHostFilePermissions interface seems like an overkill to me -- just
> aggregating 9 booleans can also be done with a single integer plus some bitmask
> constants, and is easier to extend in a binary compatible way like that. The
> typical UNIX ugo=rwxrwxrwx bitfield should be just fine.

I thought about that originally but then I figured we would want the interface to be very clear and readable for easier consumption.  The implementation could take case of bitfields as suggested but shouldn't the interface be as obvious as possible?


Comment 6 Martin Oberhuber CLA 2008-01-10 11:12:46 EST
This API is for programmers. They should be capable of dealing with bitfields. If you want to simplify it, you could do something like in IFileInfo:

/**
 * Set or reset all the permission bits from the given bitmask.
 * Example: setPermission(PERM_USER_WRITE | PERM_GROUP_WRITE, true);
 */
public void setPermission(int bitmask, boolean value);

/**
 * Test if any of the permission bits from the bitmask are set.
 * Example: getPermission(PERM_USER_WRITE | PERM_GROUP_WRITE)
 */
public boolean getPermission(int bitmask);

public int getPermissionBits();
public void setPermissionBits(int bits);

The main advantage of such a kind of API is that if you add permission bits in the future (e.g. PERM_SETUID) you can do so without changing the interface signature just by adding the new constant. Since the new constant is inlined, clients which use the new API will still be binary compatible against old versions of the framework.

But there are more advantages: 
 * Simpler code for changing / reading multiple perm bits at once
 * Supports constants like PERM_ANY_WRITE, PERM_ANY_EXECUTE which check
   multiple bits at once

If you really want to have a generic API that should also hold in the future for yet unknown kinds of permission schemes, you could also add a "Properties" like interface:

public String getPermissionAttribute(String attributeName);
public void setPermissionAttribute(String attributeName, String value);

For WinNT ACL's this could be used like

String allowedUsers = getPermissionAttribute("aclRead");

But I'm unsure if this is the right thing to do at the moment.
Comment 7 Martin Oberhuber CLA 2008-01-10 11:15:34 EST
Adding Bug #165171 and bug #180507 as blocked by this one, since this bug is for UNIX-like file systems specifically while the others are for more generic cases. We'll see what to do with those other bugs once this one is resolved.
Comment 8 David McKnight CLA 2008-01-10 12:54:03 EST
Created attachment 86578 [details]
updated patch of potential service inferfaces permissions and ownership

Here's an updated version of the permissions stuff, including an AbstractHostFilePermissions implementation.

How does this look?
Comment 9 Martin Oberhuber CLA 2008-01-10 13:01:56 EST
1.) Why do you expose set(), clear(), _permissions as "protected" API?
    This unnecessarily exposes implementation details.

2.) Why is AbstractHostFilePermissions abstract? It looks like a complete
    implementation to me. Could also be HostFilePermissions, perhaps with
    a constructor taking intial "int mask".

3.) The public static int constants are missing in the interface PERM_USER_...

4.) I'd like to see canSet... API.
Comment 10 Martin Oberhuber CLA 2008-01-10 13:02:20 EST
Also, please update your Copyright template to use year 2008 for new files.
Comment 11 David McKnight CLA 2008-01-10 13:15:29 EST
(In reply to comment #9)
> 1.) Why do you expose set(), clear(), _permissions as "protected" API?
>     This unnecessarily exposes implementation details.
> 2.) Why is AbstractHostFilePermissions abstract? It looks like a complete
>     implementation to me. Could also be HostFilePermissions, perhaps with
>     a constructor taking intial "int mask".

I was anticipating that each service may implement this slightly differently.  We do it for IHostFile so I thought it may be needed for the IHostFilePermissions too.  For example, dstore may create a DStoreFilePermissions class with a DStoreFilePermissions(DataElement) constructor (the DataElement storing the bits as determined from the remote machine).  That's why I exposed the methods as protected API.  But perhaps, it's simple enough that we don't need to specialize it.        
  
> 3.) The public static int constants are missing in the interface PERM_USER_...

I'll add the constants in my next patch update.

> 4.) I'd like to see canSet... API.

I'll add a canSet in my next patch update.

Comment 12 Martin Oberhuber CLA 2008-01-10 13:52:10 EST
This interface and implementation are so simple that exposing protected API for overriding it partially makes no sense. 

If a Dstore implementation wants to implement the interface by holding a dataElement rather than the int bitmask, the methods and data fields that you're exposing as protected are of no use to it.
Comment 13 David McKnight CLA 2008-01-10 14:02:37 EST
Created attachment 86584 [details]
next patch iteraction of potential service apis

In this patch, I've added the bit mask constants, taken out the abstract of the host file permissions implementation, added canSet APIs for the permissions service and the owner service and updated copyrights.
Comment 14 David McKnight CLA 2008-01-10 14:04:21 EST
(In reply to comment #12)
> This interface and implementation are so simple that exposing protected API for
> overriding it partially makes no sense. 
> If a Dstore implementation wants to implement the interface by holding a
> dataElement rather than the int bitmask, the methods and data fields that
> you're exposing as protected are of no use to it.

For dstore, the thought was to construct the bitmask constant from the element, but it's easy enough just to do that before constructing a concrete instance of HostFilePermissions.
Comment 15 Martin Oberhuber CLA 2008-01-10 14:11:42 EST
1.) HostFilePermissions is Copyright (c) 20078

2.) The interface is small enough that you don't need @see with all the constants

3.) Please use those decimal values that typical UNIX machines also use:
       ugo=rwxrwxrwx
    PERM_OTHERS_EXECUTE = 1 << 0;
    PERM_OTHERS_WRITE = 1 << 1;
    PERM_OTHERS_READ = 1 << 2;
    ...
    This will make it easier on the commandline, because then you can do

    chmod 200 otherfile

    just taking the octal value for the permission bits
Comment 16 David Dykstal CLA 2008-01-10 14:14:22 EST
(In reply to comment #12)
> This interface and implementation are so simple that exposing protected API for
> overriding it partially makes no sense. 
> 
> If a Dstore implementation wants to implement the interface by holding a
> dataElement rather than the int bitmask, the methods and data fields that
> you're exposing as protected are of no use to it.
> 

As a design note: I'm developing a taste for never using "protected". It is only of use when subclassing. Making data directly available to subclasses is almost never a good idea for a public API. I'd rather see protected used on a limited basis only for internal, controlled frameworks.
Comment 17 Martin Oberhuber CLA 2008-01-10 14:28:12 EST
... which goes with the general advice of many OO gurus, that composition (aggregation) of classes is usually better than extending them (derivation).
Comment 18 David McKnight CLA 2008-01-10 15:30:59 EST
Created attachment 86601 [details]
updated patch

Here's another update based on comment #15.
Comment 19 David McKnight CLA 2008-01-11 12:09:12 EST
Created attachment 86697 [details]
updated patch with dstore implementation

I've updated the interfaces to include a canGet*() apis as well since the service may need to determine this at runtime (i.e. dstore would query the command descriptors to determine whether the server has this functionality).

I've added a basic dstore implementation to the DStoreFileService and the UniversalFileSystemMiner.
Comment 20 David McKnight CLA 2008-01-11 15:10:05 EST
Created attachment 86714 [details]
updated patch with property page for exercising this

I've changed the IFileOwnerService to have both a user owner and group owner.

In this patch, I've also implemented a property page to exercise this function.  Currently, it just worked via checking for the appropriate service interfaces on the IFileService.  This will have to change to use something more adaptable but I wanted to put something out now to show the function.
Comment 21 David McKnight CLA 2008-01-15 12:52:45 EST
Created attachment 86959 [details]
patch with further evolution of the enhancement

This includes the adapter factor for getting at the appropriate permissions service given an IRemoteFile.  It also includes property sheet and table view column support for permissions, user owner and group.  In order to avoid performance and locking issues when getting the property sheet values for these new fields, we schedule a job, store results in an IRemoteFile, and then fire an property update notification.
Comment 22 David McKnight CLA 2008-01-21 13:29:38 EST
Created attachment 87427 [details]
patch to consolidate permissions and initial get support for ftp and ssh
Comment 23 David McKnight CLA 2008-01-21 13:41:22 EST
I've provided another patch which alters this stuff a bit:  

1) Consolidation of permissions services
The IFilePermissionsService and the IFileOwnerService are consolidated into one IFilePermissionsService.  IFileService is expected to implement this if the service is supported.  The group and owner are now stored as part of the IHostFilePermissions.

2) IHostFilePermissionsContainer
I've added IHostFilePermissionsContainer for IHostFile to implement when caching of IHostFilePermissions is desired.  This provides an API for getPermissions() and setPermissions(IHostFilePermissions) for an IHostFile.  The reason I didn't add these apis directly to IHostFile is that some implementations, like local, will not have this support and I didn't want to force this on the services.

3) DStore impl
I've changed the dstore implementation to the getting (and setting) of permissions, user and group in one shot, rather than as separate queries for performance purposes and because they logically belong together.

4) FTP impl
I've added get support for the FTP service. The set support still needs to be implemented.

5) SSH impl
I've added get support for the SSH service.  Currently it's storing the uid and gid for the user and group.  I'm not sure whether there's an easy way, via the SSH service to translate those into the proper strings.  The set support also still needs to be implemented.
Comment 24 Martin Oberhuber CLA 2008-01-22 12:28:10 EST
(In reply to comment #23)

1) I like the consolidation of permissions and ownership, since they really
   belong together. The one thing that I find problematic is
     canSetFilePermissions(IHostFile file)
   because on many systems, you may be able to change the permissions but
   not the ownership. That should be reflected in the UI by potentially
   disabling the controls for ownership change when this feature is not
   available.
   One way out of this dilemma might be an API like
     int IFileService#getCapabilities(IHostFile file)
   that returns a bitmask of constants regarding remote capabilities:
     FS_CAN_GET_OWNER
     FS_CAN_GET_GROUP
     FS_CAN_GET_PERMISSIONS
     FS_CAN_SET_OWNER
     FS_CAN_SET_GROUP
     FS_CAN_SET_PERMISSIONS
   that's easily extendable in a binary compatible way. When passing a 
   "null" file, the API could return general capabilities of the service.

2) I do not like that the IHostFilePermissionsContainer allows 
   setPermissions(). I really think that the IHostFile object should be
   immutable (such that clients cannot change it). The only way for a client
   to change the permissions on an IHostFile should be by changing it on the
   remote side and then re-querying the remote.
   If we allow changing the IHostFile locally we risk getting out of sync with
   what we really have on the remote. The remote side should be the only
   one who can modify the actual IHostFile. For the same reason, 
      IHostFile#getPermissions()
   should be specified as API to always return a COPY of the internal
   IHostFilePermissions because the client is allowed to modify the
   IHostFilePermissions.

   One possible API could be
   interface IFilePermissionsService {
      IHostFile setPermissions(IHostFile file, IHostFilePermissions perms);
   };
   returning the modified IHostFile in case of success, or throwing an 
   exception (and leaving the original IHostFile unchanged) in case of an
   error.

3) I like the proposed implementations. I particularly like the ability to
   set and get permissions in ASCII form as a String, because such an API
   could easily account for different conventions of representing permission
   info on different OS's (note that specific permission queries can still
   be made through the associated bitmask API).

In general, I think it's important that the Model (IHostFile) is kept separate from the Controller (IFileService) performing the actual operations. What I'm unsure about, is whether it's really necessary to keep IFilePermissionsService / IHostFilePermissionsContainer separate from the original IFileService / IHostFile. 

Given that we have abstract base classes for both, it might also be possible to have the new capabilities added to the Service interface.
Comment 25 David McKnight CLA 2008-01-22 13:35:37 EST
Created attachment 87539 [details]
updated patch with suggestions from martin

I've updated the patch based on the suggestions:

1) I've changed the can* methods to use getcapabilities()
2) I've taken out the setPermissions (and leave that to the services to set pending permissions).  Will look into checking a queue in the service layer to determine whether or not a new query is required.  Currently there's a problem where the PendingHostFilePermissions is not set soon enough so duplicate queries are sent.
Comment 26 David McKnight CLA 2008-01-29 10:54:53 EST
Since this is pretty much done I'm going to close this.   Work still needs to be done if we wish to support modification of permissions for SSH and FTP files but I think each of those should be handled in separate bugs.  For any other issues with this, I'd prefer to use a separate defect.