Documentation Archive Developer
Search

ADC Home > Reference Library > Technical Q&As > Carbon > File Management >

FSSetCatalogInfo versus UID and GID


Q: How do I use FSSetCatalogInfo to change the UID and GID of a file?

A: Apple specifically chose to ignore the UID and GID values you supply to FSSetCatalogInfo so as to improve compatibility with existing source code. The code in most applications copies a file's metadata by calling FSGetCatalogInfo on the source then calling FSSetCatalogInfo on the destination. However, Mac OS X does not let a non-root program change the UID of a file. Thus, if FSSetCatalogInfo was implemented in the obvious way and you used the standard copy algorithm to copy a file that you did not own, your program would fail with a permissions error.

At this point in time there is no way to set a file's UID or GID using the Carbon File Manager. The recommended workaround is to use the BSD call chown, as shown in Listing 1.


Listing 1. A version of FSSetCatalogInfo that sets the UID and GID

#include <CoreServices/CoreServices.h>
#include <sys/param.h>
#include <unistd.h>

static OSStatus FSSetCatalogInfoIDs(const FSRef *ref, 
                                    FSCatalogInfoBitmap whichInfo, 
                                    const FSCatalogInfo *catalogInfo)
    // A version of FSSetCatalogInfo that actually tries 
    // to set the FUID and FGID if you supply the 
    // kFSCatInfoPermissions flag.  This is the current 
    // recommended workaround for <rdar://problem/2631025>. 
    // You can supply a userID or groupID value of -1 
    // to indicate that you don't want to change the value.
{
    OSStatus                    err;
    const FSPermissionInfo *    permInfo;
    uid_t                       uid;
    gid_t                       gid;
    
    err = FSSetCatalogInfo(ref, whichInfo, catalogInfo);
    if ( (err == noErr) && (whichInfo & kFSCatInfoPermissions) ) {
        permInfo = (const FSPermissionInfo *) catalogInfo->permissions;
        uid = (uid_t) permInfo->userID;
        gid = (gid_t) permInfo->groupID;
        if (uid != -1 || gid != -1 ) {
            char filePath[MAXPATHLEN];
            
            err = FSRefMakePath(ref, (UInt8 *) filePath, sizeof(filePath));
            if (err == noErr) {
                err = chown(filePath, uid, gid);
                if (err == -1) {
                    err = errno;
                }
            }
        }
    }
    return err;
}

IMPORTANT:
The above code does not give you any special privileges. If you attempt to perform some operation that is restricted (enter man 2 chown in Terminal for information about those restrictions), FSSetCatalogInfoIDs will fail with an error. For information about how to get additional privileges, see the Authorization Services documentation.

Note:
If you discovered this problem because you're writing your own code to copy file system objects, you might consider using the code from the DTS sample code FSCopyObjects instead.


[Mar 26, 2003]