nfs-ganesha 1.4

api_fsetattr.c

Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <fcntl.h>
00007 #include <unistd.h>
00008 #include <u_signed64.h>
00009 #include <hpssclapiext.h>
00010 #include <api_internal.h>
00011 #include <acct_av_lib.h>
00012 
00013 #define BFS_SET_MAX (32)
00014 
00015 /* these functions are working in HPSS 7.x */
00016 #if (HPSS_MAJOR_VERSION < 7)
00017 
00018 /*
00019  * Local function definition
00020  */
00021 
00022 static int HPSSFSAL_Common_FileSetAttributes(apithrdstate_t * ThreadContext,    /* IN - thread context */
00023                                              ns_ObjHandle_t * ObjHandle,        /* IN - parent object handle */
00024                                              char *Path,        /* IN - path to the object */
00025                                              api_cwd_stack_t * CwdStack,        /* IN - cwd stack */
00026                                              hpss_reqid_t RequestID,    /* IN - request id */
00027                                              TYPE_CRED_HPSS * Ucred,    /* IN - user credentials */
00028                                              unsigned32 ChaseFlags,     /* IN - chase symlinks/junctions */
00029                                              hpss_fileattrbits_t SelFlagsIn,    /* IN - attributes fields to set */
00030                                              hpss_fileattr_t * AttrIn,  /* IN - input attributes */
00031                                              hpss_fileattrbits_t * SelFlagsOut, /* OUT - attributes fields set */
00032                                              hpss_fileattr_t * AttrOut);        /* OUT - attributes after change */
00033 
00034 /*============================================================================
00035  *
00036  * Function:    HPSSFSAL_FileSetAttrHandle
00037  *
00038  * Synopsis:
00039  *
00040  * int
00041  * HPSSFSAL_FileSetAttrHandle(
00042  * ns_ObjHandle_t       *ObjHandle,     ** IN  - parent object handle 
00043  * char                 *Path,          ** IN  - path to the object
00044  * TYPE_CRED_HPSS      *Ucred,         ** IN  - user credentials
00045  * hpss_fileattrbits_t  SelFlags,       ** IN - attributes fields to set
00046  * hpss_fileattr_t      *AttrIn,        ** IN  - input attributes
00047  * hpss_fileattr_t      *AttrOut)       ** OUT - attributes after change
00048  *
00049  * Description:
00050  *
00051  *      The like the hpss_FileSetAttributesHandle function
00052  *      except that it doesn't chase junctions nor symlinks.
00053  *
00054  * Other Inputs:
00055  *      None.
00056  *
00057  * Outputs:
00058  *              0 -             No error, caller has access.
00059  *
00060  * Interfaces:
00061  *      DCE pthreads, DCE/RPC, Common_FileSetAttributes
00062  *
00063  * Resources Used:
00064  *
00065  * Limitations:
00066  *
00067  * Assumptions:
00068  *
00069  * Notes:
00070  *
00071  *-------------------------------------------------------------------------*/
00072 
00073 int HPSSFSAL_FileSetAttrHandle(ns_ObjHandle_t * ObjHandle,      /* IN  - parent object handle */
00074                                char *Path,      /* IN  - path to the object */
00075                                TYPE_CRED_HPSS * Ucred,  /* IN  - user credentials */
00076                                hpss_fileattrbits_t SelFlags,    /* IN - attributes fields to set */
00077                                hpss_fileattr_t * AttrIn,        /* IN  - input attributes */
00078                                hpss_fileattr_t * AttrOut)       /* OUT - attributes after change */
00079 {
00080   static char function_name[] = "hpss_FileSetAttributesHandle";
00081   volatile long error = 0;      /* return error */
00082   hpss_reqid_t rqstid;          /* request id */
00083   TYPE_CRED_HPSS *ucred_ptr;    /* user credentials */
00084   apithrdstate_t *threadcontext;        /* thread context */
00085 
00086   API_ENTER(function_name);
00087 
00088   /*
00089    *  Initialize the thread if not already initialized.
00090    *  Get a pointer back to the thread specific context.
00091    */
00092 
00093   error = API_ClientAPIInit(&threadcontext);
00094   if(error != 0)
00095     API_RETURN(error);
00096 
00097   /*
00098    *  Check that the object handle is not NULL.
00099    */
00100 
00101   if(ObjHandle == (ns_ObjHandle_t *) NULL)
00102     API_RETURN(-EINVAL);
00103 
00104   /*
00105    *  Check that the pathname the string is not the NULL string.
00106    */
00107 
00108   if(Path != NULL && *Path == '\0')
00109     API_RETURN(-ENOENT);
00110 
00111   /*
00112    *  If user credentials were not passed, use the ones in the
00113    *  current thread context.
00114    */
00115 
00116   if(Ucred == (TYPE_CRED_HPSS *) NULL)
00117     ucred_ptr = &threadcontext->UserCred;
00118   else
00119     ucred_ptr = Ucred;
00120 
00121   /*
00122    *  Generate a unique request id.
00123    */
00124 
00125   rqstid = API_GetUniqueRequestID();
00126 
00127   /*
00128    *  Call the common routine to do most of the set attribute
00129    *  processing
00130    */
00131 
00132   error = HPSSFSAL_Common_FileSetAttributes(threadcontext,
00133                                             ObjHandle,
00134                                             Path,
00135                                             API_NULL_CWD_STACK,
00136                                             rqstid,
00137                                             ucred_ptr,
00138                                             API_CHASE_NONE,
00139                                             SelFlags, AttrIn, NULL, AttrOut);
00140 
00141   API_RETURN(error);
00142 }
00143 
00144 /*============================================================================
00145  *
00146  * Function:    Common_FileSetAttributes
00147  *
00148  * Synopsis:
00149  *
00150  * static int
00151  * HPSSFSAL_Common_FileSetAttributes(
00152  * apithrdstate_t      *ThreadContext, ** IN - thread context
00153  * ns_ObjHandle_t      *ObjHandle,     ** IN - parent object handle
00154  * char                *Path,          ** IN - path to the object
00155  * api_cwd_stack_t     *CwdStack,      ** IN - cwd stack
00156  * hpss_reqid_t        RequestID,      ** IN - request id
00157  * TYPE_CRED_HPSS     *Ucred,         ** IN - user credentials
00158  * unsigned32          ChaseFlags,     ** IN - chase symlinks/junctions
00159  * hpss_fileattrbits_t SelFlagsIn,     ** IN - attributes fields to set
00160  * hpss_fileattr_t     *AttrIn,        ** IN - input attributes
00161  * hpss_fileattrbits_t *SelFlagsOut,   ** OUT - attributes fields set
00162  * hpss_fileattr_t     *AttrOut)       ** OUT - attributes after change
00163  *
00164  *
00165  * Description:
00166  *
00167  *      The Common_FileSetAttributes function can be used to change attributes
00168  *      on an entry in the name/file system that is refered to by 'Path' and
00169  *      'ObjHandle'.
00170  *
00171  * Other Inputs:
00172  *      None.
00173  *
00174  * Outputs:
00175  *              0 -             No error, caller has access.
00176  *
00177  * Interfaces:
00178  *      DCE pthreads, DCE/RPC, API_TraversePath, API_core_SetAttrs,
00179  *      hpss_LocateServerByUUID, av_cli_AcctNameToIdx,
00180  *      av_cli_ValidateChown,  API_DetermineAcct.
00181  *
00182  * Resources Used:
00183  *
00184  * Limitations:
00185  *
00186  * Assumptions:
00187  *
00188  * Notes:
00189  *
00190  *-------------------------------------------------------------------------*/
00191 
00192 static int HPSSFSAL_Common_FileSetAttributes(apithrdstate_t * ThreadContext,    /* IN - thread context */
00193                                              ns_ObjHandle_t * ObjHandle,        /* IN - parent object handle */
00194                                              char *Path,        /* IN - path to the object */
00195                                              api_cwd_stack_t * CwdStack,        /* IN - cwd stack */
00196                                              hpss_reqid_t RequestID,    /* IN - request id */
00197                                              TYPE_CRED_HPSS * Ucred,    /* IN - user credentials */
00198                                              unsigned32 ChaseFlags,     /* IN - chase symlinks/junctions */
00199                                              hpss_fileattrbits_t SelFlagsIn,    /* IN - attributes fields to set */
00200                                              hpss_fileattr_t * AttrIn,  /* IN - input attributes */
00201                                              hpss_fileattrbits_t * SelFlagsOut, /* OUT - attributes fields set */
00202                                              hpss_fileattr_t * AttrOut) /* OUT - attributes after change */
00203 {
00204   unsigned32 call_type;         /* whether to call dmg or ns */
00205 #if  (HPSS_MAJOR_VERSION == 5)
00206   volatile long error = 0;      /* return error */
00207 #else
00208   signed32 error = 0;           /* return error */
00209 #endif
00210   static char function_name[] = "Common_FileSetAttributes";
00211   ns_ObjHandle_t obj_handle;    /* object handle of object */
00212   ns_ObjHandle_t ret_obj_handle;        /* returned object handle */
00213   hpss_Attrs_t attr;            /* attributes of file */
00214   hpss_Attrs_t attr_parent;     /* attributes of parent dir */
00215   hpss_AttrBits_t return_flags; /* attribute return flags */
00216   hpss_AttrBits_t select_flags; /* attribute flags */
00217   hpss_AttrBits_t parent_flags; /* attribute flags */
00218   char *path_object;            /* path to file */
00219   TYPE_TOKEN_HPSS ta;           /* security token */
00220   ls_map_t ls_map;              /* location information */
00221   acct_rec_t acct_code;         /* new account code */
00222   acct_rec_t cur_acct_code;     /* current account code */
00223   unsigned32 acl_options;       /* ACL Options */
00224 #if defined ( API_DMAP_SUPPORT ) && !defined (API_DMAP_GATEWAY)
00225   u_signed64 dmg_attr_bits;     /* DM attributes to set */
00226   dmg_object_attrs_t dmg_attr_in;       /* DM attributes in */
00227   dmg_object_attrs_t dmg_attr_out;      /* DM attributes returned */
00228 #endif
00229 
00230   API_ENTER(function_name);
00231 
00232   /*
00233    *  Make sure that AttrIn and AttrOut are not NULL.
00234    */
00235 
00236   if((AttrIn == (hpss_fileattr_t *) NULL) || (AttrOut == (hpss_fileattr_t *) NULL))
00237     {
00238       return (-EFAULT);
00239     }
00240 
00241   /*
00242    *  We do not allow the bitfile id to be changed via this interface.
00243    */
00244 
00245   if(chkbit64m(SelFlagsIn, CORE_ATTR_BIT_FILE_ID))
00246     {
00247       return (-EINVAL);
00248     }
00249 
00250   /*
00251    *  If the site does uid-style accounting, the user may not set the
00252    *  account code.  The user may change the account code if the site
00253    *  uses site-style accounting.
00254    *
00255    *  However, the account code must change on the hpss side whenever the
00256    *  uid is changed, and the uid must change on both the dmap and hpss
00257    *  sides.  The gateway doesn't understand account ids.  So, when the
00258    *  user changes the uid, we let the gateway change it, and when he calls
00259    *  us back to change the uid on the hpss side we also set the account id.
00260    *  Since the only information we have at that point is the uid, we set
00261    *  the account id to a) the uid, if the site does uid-style accounting,
00262    *  or b) the default account for that uid, if the site does site-style
00263    *  accounting.
00264    *
00265    *  Therefore, even if the site does site-style accounting, we can't let
00266    *  the caller specify both a new uid and a new account code different
00267    *  from the default on the same call, because we can't pass that
00268    *  nondefault account code through the gateway and because setting the
00269    *  uid and account code must be done in one operation on the hpss side.
00270    *  So we disallow setting both the uid and account code on the same call.
00271    */
00272 
00273   /*
00274    * The statement above only applies to non-gateway clients. If
00275    * this is the gateway library, just ignore the account check.
00276    */
00277 
00278 #if !defined(API_DMAP_GATEWAY)
00279   if(chkbit64m(SelFlagsIn, CORE_ATTR_ACCOUNT) && !chkbit64m(SelFlagsIn, CORE_ATTR_UID))
00280     {
00281       return (-EPERM);
00282     }
00283 #endif
00284 
00285   /*
00286    *  Allocate memory for object path.
00287    */
00288 
00289   path_object = (char *)malloc(HPSS_MAX_PATH_NAME);
00290   if(path_object == NULL)
00291     {
00292       return (-ENOMEM);
00293     }
00294 
00295   /*
00296    * Clear the return structures.
00297    */
00298 
00299   (void)memset(AttrOut, 0, sizeof(hpss_fileattr_t));
00300 
00301   /*
00302    *  Find the object to which this ObjHandle and Path refer and
00303    *  its immediate parent directory.  The Type and BitfileId will
00304    *  be returned in the attributes.
00305    */
00306 
00307   (void)memset(&select_flags, 0, sizeof(select_flags));
00308   (void)memset(&parent_flags, 0, sizeof(parent_flags));
00309 
00310 #if HPSS_MAJOR_VERSION < 7
00311   select_flags = API_AddRegisterValues(cast64m(0),
00312                                        CORE_ATTR_TYPE,
00313                                        CORE_ATTR_FILESET_ID,
00314                                        CORE_ATTR_FILESET_TYPE,
00315                                        CORE_ATTR_GATEWAY_UUID,
00316                                        CORE_ATTR_DM_HANDLE,
00317                                        CORE_ATTR_DM_HANDLE_LENGTH,
00318                                        CORE_ATTR_COS_ID,
00319                                        CORE_ATTR_USER_PERMS,
00320                                        CORE_ATTR_GROUP_PERMS,
00321                                        CORE_ATTR_OTHER_PERMS,
00322                                        CORE_ATTR_SET_UID,
00323                                        CORE_ATTR_SET_GID, CORE_ATTR_SET_STICKY, -1);
00324 
00325   parent_flags = API_AddRegisterValues(cast64m(0),
00326                                        CORE_ATTR_FILESET_ID,
00327                                        CORE_ATTR_FILESET_TYPE,
00328                                        CORE_ATTR_GATEWAY_UUID,
00329                                        CORE_ATTR_DM_HANDLE,
00330                                        CORE_ATTR_DM_HANDLE_LENGTH, CORE_ATTR_COS_ID, -1);
00331 #else
00332   select_flags = API_AddRegisterValues(cast64m(0),
00333                                        CORE_ATTR_TYPE,
00334                                        CORE_ATTR_UID,
00335                                        CORE_ATTR_GID,
00336                                        CORE_ATTR_ACCOUNT,
00337                                        CORE_ATTR_REALM_ID,
00338                                        CORE_ATTR_COS_ID,
00339                                        CORE_ATTR_USER_PERMS,
00340                                        CORE_ATTR_GROUP_PERMS,
00341                                        CORE_ATTR_OTHER_PERMS, CORE_ATTR_MODE_PERMS, -1);
00342 
00343   parent_flags = API_AddRegisterValues(cast64m(0), CORE_ATTR_COS_ID, -1);
00344 #endif
00345 
00346   /*
00347    * Zero the output structures
00348    */
00349 
00350   memset(&attr, 0, sizeof(attr));
00351   memset(&attr_parent, 0, sizeof(attr_parent));
00352   memset(&obj_handle, 0, sizeof(obj_handle));
00353 
00354   error = API_TraversePath(ThreadContext,
00355                            RequestID,
00356                            Ucred,
00357                            ObjHandle,
00358                            Path,
00359                            CwdStack,
00360                            ChaseFlags,
00361                            0,
00362                            0,
00363                            select_flags,
00364                            parent_flags,
00365                            API_NULL_CWD_STACK, &obj_handle, &attr, NULL, &attr_parent,
00366 #if HPSS_MAJOR_VERSION < 7
00367                            &ta, path_object,
00368 #else
00369                            NULL,
00370 #endif
00371                            NULL);
00372 
00373   if(error != 0)
00374     {
00375       API_DEBUG_FPRINTF(DebugFile, &RequestID,
00376                         "%s: Could get attributes, error=%d\n", function_name, error);
00377     }
00378   else
00379     {
00380       /*
00381        * Check the flags in the returned handle to determine
00382        * if the object is the root of a fileset. In this case,
00383        * the object is its own parent.
00384        */
00385 
00386       if(obj_handle.Flags & NS_OH_FLAG_FILESET_ROOT)
00387         {
00388           memcpy(&attr_parent, &attr, sizeof(attr_parent));
00389           strcpy(path_object, ".");
00390         }
00391 
00392       /*
00393        *  Store the returned object handle and attributes in the
00394        *  hpss_fileattrs_t structure to be returned to the caller.
00395        */
00396 
00397       AttrOut->ObjectHandle = obj_handle;
00398 
00399       /*
00400        *  If being asked to changed the COS information and there
00401        *  is a COS specified for the fileset where the file resides,
00402        *  and the new COS will not match the fileset COS (I can't
00403        *  image how that can happen - but...), then set an error.
00404        */
00405 
00406       if(chkbit64m(SelFlagsIn, CORE_ATTR_COS_ID)
00407          && (attr_parent.COSId != 0) && (AttrIn->Attrs.COSId != attr_parent.COSId))
00408         {
00409           error = -EPERM;
00410           API_DEBUG_FPRINTF(DebugFile, &RequestID,
00411                             "%s: File is in a fileset with an"
00412                             " assigned COS.\n", function_name);
00413           if(path_object != NULL)
00414             free(path_object);
00415           return (error);
00416         }
00417 #if ( HPSS_MAJOR_VERSION < 7 )
00418       /*
00419        *  Determine whether to call the dmg or ns based on whether the
00420        *  parent directory is dmap managed.
00421        */
00422 
00423 #if ( HPSS_MAJOR_VERSION == 5 )
00424       call_type = API_DetermineCall(attr_parent.FilesetType, (long *)&error);
00425 #elif ( HPSS_MAJOR_VERSION == 6 )
00426       call_type = API_DetermineCall(attr_parent.FilesetType, &error);
00427 #endif
00428 
00429       if(call_type == API_CALL_DMG)
00430         {
00431 
00432 #if defined ( API_DMAP_SUPPORT ) && !defined ( API_DMAP_GATEWAY )
00433 
00434           /*
00435            *  The parent is dmap-managed.  Call the dmap gateway.
00436            *
00437            *  Only the fields checked below may be changed by a call to
00438            *  dmg_hp_setattrs.  But the user may want to set other fields
00439            *  in the object on the same call.  Therefore, the client api
00440            *  set attributes calls work a little differently than other
00441            *  calls.  They first call the gateway to set the attributes it
00442            *  recognizes; it will set them on the dmap side and then make
00443            *  a call back to hpss to set them here.  If the caller specified
00444            *  additional attributes which the dmap doesn't recognize, the
00445            *  hpss set attributes routines will then call the local ns and
00446            *  bfs to set just those.
00447            *
00448            *  After we've set these fields via the gateway, we remove the
00449            *  bits from the ns and bfs selection flags so we won't ask the
00450            *  ns and bfs to set them again.
00451            */
00452 
00453           memset(&dmg_attr_in, 0, sizeof(dmg_attr_in));
00454           memset(&dmg_attr_out, 0, sizeof(dmg_attr_out));
00455 
00456           /* Set the dmg attributes from the existing NS attrs - 1599 */
00457           dmg_attr_in.Attrs.Attrs = attr;
00458           dmg_attr_in.Attrs.ObjectHandle = obj_handle;
00459           dmg_attr_bits = cast64m(0);
00460           acl_options = 0;
00461 
00462           /*
00463            * 1599 -
00464            * Now, depending on what attribute flags were set,
00465            * overwrite the corresponding attribute object fields
00466            * with the information supplied by the user.
00467            */
00468 
00469           /*
00470            * Owner
00471            */
00472 
00473           if(chkbit64m(SelFlagsIn, CORE_ATTR_UID))
00474             {
00475               /*
00476                *  The dmg doesn't know anything about the account id, yet
00477                *  we must change it in both the ns and bfs if we are changing
00478                *  the owner.  That's okay.  Call the dmg to change the owner.
00479                *  It will call us back and we'll follow the logic to change
00480                *  the owner from the hpss side.  At that point, we'll catch
00481                *  the uid change and make the corresponding account change
00482                *  on the hpss side.
00483                */
00484 
00485               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00486                                      (low32m(dmg_attr_bits) | CHANGE_OWNER));
00487               dmg_attr_in.Attrs.Attrs.UID = AttrIn->Attrs.UID;
00488             }
00489 
00490           /*
00491            * Group
00492            */
00493 
00494           if(chkbit64m(SelFlagsIn, CORE_ATTR_GID))
00495             {
00496               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00497                                      (low32m(dmg_attr_bits) | CHANGE_GROUP));
00498 
00499               dmg_attr_in.Attrs.Attrs.GID = AttrIn->Attrs.GID;
00500             }
00501 
00502           /*
00503            * Permissions
00504            */
00505 
00506           if(chkbit64m(SelFlagsIn, CORE_ATTR_USER_PERMS))
00507             {
00508               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00509                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00510               dmg_attr_in.Attrs.Attrs.UserPerms = AttrIn->Attrs.UserPerms;
00511             }
00512           if(chkbit64m(SelFlagsIn, CORE_ATTR_GROUP_PERMS))
00513             {
00514               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00515                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00516               dmg_attr_in.Attrs.Attrs.GroupPerms = AttrIn->Attrs.GroupPerms;
00517             }
00518           if(chkbit64m(SelFlagsIn, CORE_ATTR_OTHER_PERMS))
00519             {
00520               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00521                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00522               dmg_attr_in.Attrs.Attrs.OtherPerms = AttrIn->Attrs.OtherPerms;
00523             }
00524           if(chkbit64m(SelFlagsIn, CORE_ATTR_SET_UID))
00525             {
00526               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00527                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00528               dmg_attr_in.Attrs.Attrs.SetUIDBit = AttrIn->Attrs.SetUIDBit;
00529             }
00530           if(chkbit64m(SelFlagsIn, CORE_ATTR_SET_GID))
00531             {
00532               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00533                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00534               dmg_attr_in.Attrs.Attrs.SetGIDBit = AttrIn->Attrs.SetGIDBit;
00535             }
00536           if(chkbit64m(SelFlagsIn, CORE_ATTR_SET_STICKY))
00537             {
00538               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00539                                      (low32m(dmg_attr_bits) | CHANGE_MODE));
00540               dmg_attr_in.Attrs.Attrs.SetStickyBit = AttrIn->Attrs.SetStickyBit;
00541             }
00542 
00543           /*
00544            * Modification/Access times
00545            */
00546 
00547           if(chkbit64m(SelFlagsIn, CORE_ATTR_TIME_LAST_READ))
00548             {
00549               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00550                                      (low32m(dmg_attr_bits) | CHANGE_UTIME));
00551               dmg_attr_in.Attrs.Attrs.TimeLastRead = AttrIn->Attrs.TimeLastRead;
00552             }
00553 
00554           if(chkbit64m(SelFlagsIn, CORE_ATTR_TIME_LAST_WRITTEN))
00555             {
00556               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00557                                      (low32m(dmg_attr_bits) | CHANGE_UTIME));
00558               dmg_attr_in.Attrs.Attrs.TimeLastWritten = AttrIn->Attrs.TimeLastWritten;
00559             }
00560 
00561           /*
00562            * Size
00563            */
00564 
00565           if(chkbit64m(SelFlagsIn, CORE_ATTR_DATA_LENGTH))
00566             {
00567               dmg_attr_bits = bld64m(high32m(dmg_attr_bits),
00568                                      (low32m(dmg_attr_bits) | CHANGE_FILESIZE));
00569               dmg_attr_in.Attrs.Attrs.DataLength = AttrIn->Attrs.DataLength;
00570             }
00571 
00572           error = API_dmg_SetAttrs(ThreadContext,
00573                                    RequestID,
00574                                    Ucred,
00575                                    &attr_parent.GatewayUUID,
00576                                    attr_parent.FilesetId,
00577                                    attr_parent.DMHandle,
00578                                    attr_parent.DMHandleLength,
00579                                    path_object,
00580                                    dmg_attr_bits,
00581                                    &dmg_attr_in, acl_options, &dmg_attr_out);
00582 
00583           if(error != 0)
00584             {
00585               API_DEBUG_FPRINTF(DebugFile, &RequestID,
00586                                 "%s: API_dmg_SetAttrs() failed,"
00587                                 " error=%d.\n", function_name, error);
00588             }
00589           else
00590             {
00591               hpss_AttrBits_t attr_flags;
00592 
00593               /*
00594                *  Save the hpss portion of the returned dmg attributes in
00595                *  the structure to be returned to the caller.
00596                */
00597 
00598               AttrOut->Attrs = dmg_attr_out.Attrs.Attrs;
00599 
00600               /*
00601                *  Now turn off any of these bits in the input selection flags,
00602                *  so if we have to call the hpss side below to set other 
00603                *  fields, we won't reset these.
00604                */
00605 
00606               attr_flags = API_AddRegisterValues(cast64m(0),
00607                                                  CORE_ATTR_UID,
00608                                                  CORE_ATTR_GID,
00609                                                  CORE_ATTR_USER_PERMS,
00610                                                  CORE_ATTR_GROUP_PERMS,
00611                                                  CORE_ATTR_OTHER_PERMS,
00612                                                  CORE_ATTR_SET_UID,
00613                                                  CORE_ATTR_SET_GID,
00614                                                  CORE_ATTR_SET_STICKY,
00615                                                  CORE_ATTR_TIME_LAST_READ,
00616                                                  CORE_ATTR_TIME_LAST_WRITTEN,
00617                                                  CORE_ATTR_DATA_LENGTH, -1);
00618 
00619               SelFlagsIn = and64(SelFlagsIn, not64(attr_flags));
00620             }
00621 #else
00622           error = EACCES;
00623           API_DEBUG_FPRINTF(DebugFile, &RequestID,
00624                             "%s: No dmap support compiled in.\n", function_name);
00625 #endif
00626         }                       /* end "if call_type == DMG" */
00627 #endif                          /* end of version < 7 */
00628 
00629       if(error == 0)
00630         {
00631           /*
00632            *  In most calls that might have to call the gateway, there would
00633            *  be an "else" clause here; we would call the gateway or the hpss
00634            *  side but not both.  For set attributes routines, however,
00635            *  we proceed with this code unconditionally.  If we did already
00636            *  call the gateway, we might still have attributes to set 
00637            *  which the gateway doesn't recognize.  If we didn't call the
00638            *  gateway, because call_type was API_CALL_HPSS, then now's the
00639            *  time to do it.
00640            *
00641            *  First set the returned bits structures.
00642            */
00643 
00644           return_flags = SelFlagsIn;
00645 
00646           /*
00647            *  Next set things up to handle any account code changes:
00648            *
00649            *  If the UID is changed, then the account id must also change.
00650            *
00651            *  Only root is allowed to change the UID, but we don't check for
00652            *  that here; we just pass it through to the name server and let
00653            *  him check the security.  
00654            *
00655            *  If the account code changes, either because the use
00656            *  specifically requested it or because the UID changed, it 
00657            *  must change in both the name and the bitfile attributes
00658            *  and must be changed to the same value in both.
00659            *
00660            *  Since we don't allow users to specify both an account code
00661            *  change and a uid change in the same call, by the time we
00662            *  get here only one selection bit or the other might be set,
00663            *  but not both.
00664            */
00665 
00666           if(chkbit64m(SelFlagsIn, CORE_ATTR_UID))
00667             {
00668               /*
00669                * Do account validation -
00670                * First, get the Core Server's site id.
00671                */
00672 
00673               error = hpss_LocateServerByUUID(RequestID,
00674                                               obj_handle.CoreServerUUID, &ls_map);
00675               if(error != 0)
00676                 {
00677                   API_DEBUG_FPRINTF(DebugFile, &RequestID,
00678                                     "%s: Could not get location, error=%d\n",
00679                                     function_name, error);
00680                 }
00681               else
00682                 {
00683                   /*
00684                    * Get the user's current session account code.
00685                    */
00686 
00687                   error = API_DetermineAcct(Ucred,
00688                                             ThreadContext,
00689                                             obj_handle.CoreServerUUID,
00690                                             RequestID, &ls_map.SiteId, &cur_acct_code);
00691                   if(error != 0)
00692                     {
00693                       API_DEBUG_FPRINTF(DebugFile, &RequestID,
00694                                         "%s: couldn't determine"
00695                                         " account code, error= %d\n",
00696                                         function_name, error);
00697                     }
00698                   else
00699                     {
00700                       /*
00701                        * Ask Account Validation for the account code
00702                        * to use by passing in the file's old and new
00703                        * attributes and the user's current session account.
00704                        */
00705 
00706 #if HPSS_MAJOR_VERSION == 5
00707                       error = av_cli_ValidateChown(ls_map.SiteId,
00708                                                    RequestID,
00709                                                    attr.CellId,
00710                                                    attr.UID,
00711                                                    attr.GID,
00712                                                    attr.Account,
00713                                                    attr.CellId,
00714                                                    AttrIn->Attrs.UID,
00715                                                    attr.GID, cur_acct_code, &acct_code);
00716 #elif (HPSS_MAJOR_VERSION == 6)||(HPSS_MAJOR_VERSION == 7)
00717                       error = av_cli_ValidateChown(ls_map.SiteId,
00718                                                    RequestID,
00719                                                    attr.RealmId,
00720                                                    attr.UID,
00721                                                    attr.GID,
00722                                                    attr.Account,
00723                                                    attr.RealmId,
00724                                                    AttrIn->Attrs.UID,
00725                                                    attr.GID, cur_acct_code, &acct_code);
00726 #endif
00727 
00728                       if(error != 0)
00729                         {
00730                           API_DEBUG_FPRINTF(DebugFile, &RequestID,
00731                                             "%s: av_cli_ValidateChown"
00732                                             " failed using the default"
00733                                             " account code, error=%d\n",
00734                                             function_name, error);
00735                         }
00736                     }
00737                 }
00738 
00739               if(error == 0)
00740                 {
00741                   AttrIn->Attrs.Account = acct_code;
00742                   SelFlagsIn = orbit64m(SelFlagsIn, CORE_ATTR_ACCOUNT);
00743                 }
00744 
00745             }
00746           else if(chkbit64m(SelFlagsIn, CORE_ATTR_ACCOUNT))
00747             {
00748               /*
00749                * User is setting account id, but not uid. 
00750                */
00751 
00752               /*
00753                * Do account validation -
00754                * First, get the Core Server's site id.
00755                */
00756 
00757               error = hpss_LocateServerByUUID(RequestID,
00758                                               obj_handle.CoreServerUUID, &ls_map);
00759               if(error != 0)
00760                 {
00761                   API_DEBUG_FPRINTF(DebugFile, &RequestID,
00762                                     "%s: Could not get location, error=%d\n",
00763                                     function_name, error);
00764                 }
00765               else
00766                 {
00767                   /* 
00768                    * Validate that the account code can be changed.
00769                    */
00770 
00771 #if HPSS_MAJOR_VERSION == 5
00772                   error = av_cli_ValidateChacct(ls_map.SiteId,
00773                                                 RequestID,
00774                                                 Ucred->DCECellId,
00775                                                 Ucred->SecPWent.Uid,
00776                                                 attr.CellId,
00777                                                 attr.UID,
00778                                                 attr.GID,
00779                                                 attr.Account,
00780                                                 AttrIn->Attrs.Account, &acct_code);
00781 #elif (HPSS_MAJOR_VERSION == 6)||(HPSS_MAJOR_VERSION == 7)
00782                   error = av_cli_ValidateChacct(ls_map.SiteId,
00783                                                 RequestID,
00784                                                 Ucred->RealmId,
00785                                                 Ucred->Uid,
00786                                                 attr.RealmId,
00787                                                 attr.UID,
00788                                                 attr.GID,
00789                                                 attr.Account,
00790                                                 AttrIn->Attrs.Account, &acct_code);
00791 #endif
00792                   if(error != 0)
00793                     {
00794                       API_DEBUG_FPRINTF(DebugFile, &RequestID,
00795                                         "%s: av_cli_ValidateChacct failed."
00796                                         " using the account code %d,"
00797                                         " error=%d\n", function_name,
00798                                         AttrIn->Attrs.Account, error);
00799                     }
00800                 }
00801             }
00802 
00803           if(error == 0)
00804             {
00805               (void)memset(AttrOut, 0, sizeof(*AttrOut));
00806 
00807               error = API_core_SetAttrs(ThreadContext,
00808                                         RequestID,
00809                                         Ucred,
00810                                         &obj_handle,
00811                                         NULL,
00812                                         SelFlagsIn,
00813                                         &AttrIn->Attrs, return_flags, &AttrOut->Attrs);
00814 
00815               if(error != 0)
00816                 {
00817                   API_DEBUG_FPRINTF(DebugFile, &RequestID,
00818                                     "%s: Could not set attributes,"
00819                                     " error=%d\n", function_name, error);
00820                 }
00821             }
00822         }
00823     }
00824 
00825   /*
00826    * Free the locally used path name
00827    */
00828 
00829   if(path_object != NULL)
00830     free(path_object);
00831 
00832   /*
00833    *  If the user wanted them, return the out bits.
00834    *  Note that these are always 0 if we called the
00835    *  dmg; it doesn't return any out bits.
00836    */
00837 
00838   if(SelFlagsOut)
00839     *SelFlagsOut = return_flags;
00840 
00841   return (error);
00842 
00843 }
00844 
00845 #endif                          /* hpss 7+ */