nfs-ganesha 1.4

api_mkdir.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 <u_signed64.h>
00008 #include <hpssclapiext.h>
00009 #include <api_internal.h>
00010 #include <acct_av_lib.h>
00011 
00012 /*
00013  * Prototype(s) for static routines.
00014  */
00015 
00016 static int
00017 HPSSFSAL_Common_Mkdir(apithrdstate_t * ThreadContext,
00018                       ns_ObjHandle_t * ObjHandle,
00019                       char *Path,
00020                       api_cwd_stack_t * CwdStack,
00021                       int Mode,
00022                       TYPE_CRED_HPSS * Ucred,
00023                       ns_ObjHandle_t * RetObjHandle, hpss_Attrs_t * RetAttrs);
00024 
00025 /*============================================================================
00026  *
00027  * Function:    hpss_MkdirHandle
00028  *
00029  * Synopsis:
00030  *
00031  * int
00032  * HPSSFSAL_MkdirHandle(
00033  * ns_ObjHandle_t    *ObjHandle,    ** IN - handle of parent directory
00034  * char              *Path,         ** IN - path of directory
00035  * mode_t            Mode,          ** IN - perm bits for new directory
00036  * hsec_UserCred_t   *Ucred,        ** IN - user credentials
00037  * ns_ObjHandle_t    *HandleOut,    ** OUT - returned object handle
00038  * hpss_Attrs_t      *AttrsOut)      ** OUT - returned VFS attributes
00039  *
00040  * Description:
00041  *
00042  *    The 'hpss_MkdirHandle' function creates a new directory with the name
00043  *    'Path', taken relative to the directory indicated by 'ObjHandle'.
00044  *    The directory permission bits of the new directory are initialized by
00045  *    'Mode', and modified by the file creation mask of the thread.  The
00046  *    newly created directory's object handle and attributes are
00047  *    returned in the areas pointed to by 'RetObjHandle' and
00048  *    'RetVAttrs', respectively.
00049  *
00050  * Other Inputs:
00051  *    None.
00052  *
00053  * Outputs:
00054  *    0 -        No error. New directory created.
00055  *
00056  * Interfaces:
00057  *    DCE pthreads, DCE/RPC, HPSSFSAL_Common_Mkdir.
00058  *
00059  * Resources Used:
00060  *
00061  * Limitations:
00062  *
00063  * Assumptions:
00064  *
00065  * Notes:
00066  *
00067  *-------------------------------------------------------------------------*/
00068 
00069 int HPSSFSAL_MkdirHandle(ns_ObjHandle_t * ObjHandle,    /* IN - handle of parent directory */
00070                          char *Path,    /* IN - path of directory */
00071                          mode_t Mode,   /* IN - perm bits for new directory */
00072                          TYPE_CRED_HPSS * Ucred,        /* IN - user credentials */
00073                          ns_ObjHandle_t * HandleOut,    /* OUT - returned object handle */
00074                          hpss_Attrs_t * AttrsOut)       /* OUT - returned attributes */
00075 {
00076   long error = 0;
00077   apithrdstate_t *threadcontext;
00078   TYPE_CRED_HPSS *ucred_ptr;
00079 
00080   API_ENTER("hpss_MkdirHandle");
00081 
00082   /*
00083    *  Initialize the thread if not already initialized.
00084    *  Get a pointer back to the thread specific context.
00085    */
00086 
00087   error = API_ClientAPIInit(&threadcontext);
00088   if(error != 0)
00089     API_RETURN(error);
00090 
00091   /*
00092    *  Check that the object handle is not NULL.
00093    */
00094 
00095   if(ObjHandle == (ns_ObjHandle_t *) NULL)
00096     API_RETURN(-EINVAL);
00097 
00098   /*
00099    *  Check that there is a name for the new object
00100    */
00101 
00102   if(Path == NULL)
00103     API_RETURN(-EFAULT);
00104 
00105   if(*Path == '\0')
00106     API_RETURN(-ENOENT);
00107 
00108   /*
00109    *  If user credentials were not passed, use the ones in the
00110    *  current thread context.
00111    */
00112 
00113   if(Ucred == (TYPE_CRED_HPSS *) NULL)
00114     ucred_ptr = &threadcontext->UserCred;
00115   else
00116     ucred_ptr = Ucred;
00117 
00118   error = HPSSFSAL_Common_Mkdir(threadcontext,
00119                                 ObjHandle,
00120                                 Path,
00121                                 API_NULL_CWD_STACK, Mode, ucred_ptr, HandleOut, AttrsOut);
00122 
00123   API_RETURN(error);
00124 }
00125 
00126 /*============================================================================
00127  *
00128  * Function:    HPSSFSAL_Common_Mkdir
00129  *
00130  * Synopsis:
00131  *
00132  * static int
00133  * HPSSFSAL_Common_Mkdir(
00134  * apithrdstate_t    *ThreadContext,    ** IN - thread context
00135  * ns_ObjHandle_t    *ObjHandle,        ** IN - handle of parent directory
00136  * char              *Path,             ** IN - path of directory
00137  * mode_t            Mode,              ** IN - perm bits for new directory
00138  * hsec_UserCred_t   *Ucred,            ** IN - user credentials
00139  * ns_ObjHandle_t    *RetObjHandle,     ** OUT - returned object handle
00140  * hpss_Attrs_t      *RetAttrs)        ** OUT - returned attributes
00141  *
00142  * Description:
00143  *
00144  *    The 'HPSSFSAL_Common_Mkdir' function performs the common processing for
00145  *    hpss_Mkdir, hpss_MkdirHandle, and hpss_MkdirDMHandle functions.
00146  *
00147  * Other Inputs:
00148  *    None.
00149  *
00150  * Outputs:
00151  *    0 -        No error. New directory created.
00152  *
00153  * Interfaces:
00154  *    DCE pthreads, DCE/RPC, API_core_MkDir, API_ConvertPosixModeToMode,
00155  *    API_TraversePath, API_DetermineAcct, av_cli_ValidateCreate,
00156  *    API_AddRegisterValues
00157  *
00158  * Resources Used:
00159  *
00160  * Limitations:
00161  *
00162  * Assumptions:
00163  *
00164  * Notes:
00165  *
00166  *-------------------------------------------------------------------------*/
00167 
00168 static int
00169 HPSSFSAL_Common_Mkdir(apithrdstate_t * ThreadContext,
00170                       ns_ObjHandle_t * ObjHandle,
00171                       char *Path,
00172                       api_cwd_stack_t * CwdStack,
00173                       int Mode,
00174                       TYPE_CRED_HPSS * Ucred,
00175                       ns_ObjHandle_t * RetObjHandle, hpss_Attrs_t * RetAttrs)
00176 {
00177 #if HPSS_MAJOR_VERSION < 7
00178   call_type_t call_type;
00179 #endif
00180 #if HPSS_MAJOR_VERSION == 5
00181   volatile long error = 0;      /* return error */
00182 #else
00183   signed32 error = 0;           /* return error */
00184 #endif
00185   static char function_name[] = "HPSSFSAL_Common_Mkdir";
00186   ns_ObjHandle_t objhandle_parent;
00187   ns_ObjHandle_t objhandle_newdir;
00188   hpss_Attrs_t attr_parent;
00189   hpss_Attrs_t attr_newdir_in;
00190   hpss_Attrs_t attr_newdir_out;
00191   char *path_parent;
00192   char *path_newdir;
00193   retry_cb_t retry_cb;
00194   hpss_reqid_t rqstid;
00195   hpss_AttrBits_t select_flags;
00196   hpss_AttrBits_t update_flags;
00197   acct_rec_t new_acct_code;
00198   acct_rec_t temp_acct_code;
00199   TYPE_UUID_HPSS siteId;
00200   TYPE_TOKEN_HPSS ta;
00201 #if defined ( API_DMAP_SUPPORT ) && !defined ( API_DMAP_GATEWAY )
00202   byte dm_handle[MAX_DMEPI_HANDLE_SIZE];
00203   unsigned32 dm_handle_length;
00204 #endif
00205 
00206   API_ENTER(function_name);
00207 
00208   /*
00209    * Break the path into a path and a name, so that
00210    * we can get information about the parent.
00211    */
00212 
00213   path_parent = malloc(HPSS_MAX_PATH_NAME);
00214   if(path_parent == NULL)
00215     {
00216       return (-ENOMEM);
00217     }
00218 
00219   path_newdir = malloc(HPSS_MAX_PATH_NAME);
00220   if(path_newdir == NULL)
00221     {
00222       free(path_parent);
00223       return (-ENOMEM);
00224     }
00225 
00226   error = API_DivideFilePath(Path, path_parent, path_newdir);
00227 
00228   if(error != 0)
00229     {
00230       free(path_parent);
00231       free(path_newdir);
00232       return (error);
00233     }
00234 
00235   /*
00236    *  Get a valid request id.
00237    */
00238 
00239   rqstid = API_GetUniqueRequestID();
00240 
00241   /*
00242    * Get an object handle and ns attributes for the parent
00243    * directory in which the new directory is to be created.
00244    * Determine from the attributes of the parent directory
00245    * whether it is dmap managed or not, and from that determine
00246    * whether to call the dmap gateway or the name server to
00247    * create the new directory.
00248    */
00249 
00250   (void)memset(&attr_parent, 0, sizeof(attr_parent));
00251   (void)memset(&objhandle_parent, 0, sizeof(objhandle_parent));
00252 
00253   select_flags = API_AddRegisterValues(cast64m(0), CORE_ATTR_ACCOUNT,
00254 #if HPSS_MAJOR_VERSION < 7
00255                                        CORE_ATTR_FILESET_ID,
00256                                        CORE_ATTR_FILESET_TYPE,
00257                                        CORE_ATTR_GATEWAY_UUID,
00258                                        CORE_ATTR_DM_HANDLE, CORE_ATTR_DM_HANDLE_LENGTH,
00259 #endif
00260                                        -1);
00261 
00262   error = API_TraversePath(ThreadContext,
00263                            rqstid,
00264                            Ucred,
00265                            ObjHandle,
00266                            path_parent,
00267                            CwdStack,
00268                            API_CHASE_ALL,
00269                            0,
00270                            0,
00271                            select_flags,
00272                            cast64m(0),
00273                            API_NULL_CWD_STACK, &objhandle_parent, &attr_parent,
00274 #if HPSS_MAJOR_VERSION < 7
00275                            NULL,
00276 #endif
00277                            NULL, NULL, NULL, NULL);
00278 
00279   if(error != 0)
00280     {
00281       API_DEBUG_FPRINTF(DebugFile, &rqstid,
00282                         "%s: Could not get attributes.\n", function_name);
00283     }
00284   else
00285     {
00286       /*
00287        *  Check to see if we need to return the attributes of
00288        *  the newly created directory and set up the select flags
00289        *  appropriately.
00290        */
00291 
00292       if(RetAttrs != (hpss_Attrs_t *) NULL)
00293         {
00294           select_flags = API_AddAllRegisterValues(MAX_CORE_ATTR_INDEX);
00295         }
00296       else
00297         {
00298           select_flags = cast64m(0);
00299         }
00300 
00301       /*
00302        * Determine the appropriate accounting to use.
00303        */
00304 
00305       error = API_DetermineAcct(Ucred,
00306                                 ThreadContext,
00307                                 objhandle_parent.CoreServerUUID,
00308                                 rqstid, &siteId, &temp_acct_code);
00309       if(error != 0)
00310         {
00311           API_DEBUG_FPRINTF(DebugFile, &rqstid,
00312                             "%s: Could not determine which"
00313                             " account to use.\n", function_name);
00314         }
00315       else
00316         {
00317           /*
00318            * Validate the account.
00319            */
00320 #if HPSS_MAJOR_VERSION == 5
00321           error = av_cli_ValidateCreate(siteId,
00322                                         rqstid,
00323                                         Ucred->DCECellId,
00324                                         Ucred->SecPWent.Uid,
00325                                         Ucred->SecPWent.Gid,
00326                                         temp_acct_code,
00327                                         attr_parent.Account, &new_acct_code);
00328 #elif (HPSS_MAJOR_VERSION == 6) || (HPSS_MAJOR_VERSION == 7)
00329           error = av_cli_ValidateCreate(siteId,
00330                                         rqstid,
00331                                         Ucred->RealmId,
00332                                         Ucred->Uid,
00333                                         Ucred->Gid,
00334                                         temp_acct_code,
00335                                         attr_parent.Account, &new_acct_code);
00336 #endif
00337 
00338           if(error != 0)
00339             {
00340               API_DEBUG_FPRINTF(DebugFile, &rqstid,
00341                                 "%s: Could not validate"
00342                                 " the account.\n", function_name);
00343             }
00344         }
00345     }
00346 
00347   if(error == 0)
00348     {
00349 
00350 #if HPSS_MAJOR_VERSION < 7
00351 
00352       /*
00353        * Do we call the dmap gateway or the name server?
00354        */
00355 
00356 #if HPSS_MAJOR_VERSION == 5
00357       call_type = API_DetermineCall(attr_parent.FilesetType, (long *)&error);
00358 #elif HPSS_MAJOR_VERSION == 6
00359       call_type = API_DetermineCall(attr_parent.FilesetType, &error);
00360 #endif
00361 
00362       switch (call_type)
00363         {
00364 
00365         case API_CALL_DMG:
00366 
00367 #if defined ( API_DMAP_SUPPORT ) && !defined ( API_DMAP_GATEWAY )
00368           /*
00369            * Call the dmap gateway to create the file.  This will
00370            * have the side effect that the dmap will call us to
00371            * create the directory on the hpss side.  By the time this
00372            * call returns, the directory will exist on both sides.
00373            */
00374 
00375           Ucred->CurAccount = new_acct_code;
00376           memset(dm_handle, 0, (sizeof(byte) * MAX_DMEPI_HANDLE_SIZE));
00377           memset(&dm_handle_length, 0, sizeof(unsigned32));
00378 
00379           /*
00380            * The mode should have the directory bit set and
00381            * the umask bits reset.
00382            */
00383 
00384           Mode |= S_IFDIR;
00385           Mode &= ~(ThreadContext->Umask);
00386 
00387           error = API_dmg_Create(ThreadContext, rqstid, Ucred, &attr_parent.GatewayUUID, attr_parent.FilesetId, attr_parent.DMHandle, attr_parent.DMHandleLength, path_newdir, Mode, NS_OBJECT_TYPE_DIRECTORY, NULL,    /* cos hints in */
00388                                  NULL,  /* cos hints priority */
00389                                  dm_handle, (unsigned32 *) & dm_handle_length, NULL);   /* cos hints out */
00390 
00391           if(error != 0)
00392             {
00393               API_DEBUG_FPRINTF(DebugFile, &rqstid,
00394                                 "%s: API_dmg_Create failed.\n", function_name);
00395             }
00396           else
00397             {
00398               /*
00399                * If the caller asked for them, obtain the hpss attributes
00400                * and an object handle for the new directory.
00401                *
00402                * ChaseSymlinks and ChaseJunctions shouldn't matter at
00403                * this point; the object should be a directory.
00404                */
00405 
00406               if(RetObjHandle || RetVAttrs)
00407                 {
00408                   error = API_TraversePath(ThreadContext,
00409                                            rqstid,
00410                                            Ucred,
00411                                            &objhandle_parent,
00412                                            path_newdir,
00413                                            CwdStack,
00414                                            API_CHASE_NONE,
00415                                            0,
00416                                            0,
00417                                            select_flags,
00418                                            cast64m(0),
00419                                            API_NULL_CWD_STACK,
00420                                            &objhandle_newdir,
00421                                            NULL,
00422                                            NULL, &attr_newdir_out, NULL, NULL, NULL);
00423 
00424                   if(error != 0)
00425                     {
00426                       API_DEBUG_FPRINTF(DebugFile, &rqstid,
00427                                         "%s: Could not get attributes"
00428                                         " of new directory.\n", function_name);
00429                     }
00430                 }
00431             }
00432 #else
00433           error = EACCES;
00434           API_DEBUG_FPRINTF(DebugFile, &rqstid,
00435                             "%s: No dmap support compiled in.\n", function_name);
00436 #endif
00437           break;
00438 
00439         case API_CALL_HPSS:
00440 
00441 #endif                          /* HPSS < 7 */
00442 
00443           /*
00444            * Set up the parameters for the new directory.
00445            */
00446 
00447           (void)memset(&attr_newdir_out, 0, sizeof(attr_newdir_out));
00448           (void)memset(&attr_newdir_in, 0, sizeof(attr_newdir_in));
00449 
00450           attr_newdir_in.Account = new_acct_code;
00451 
00452           API_ConvertPosixModeToMode(Mode & ~(ThreadContext->Umask), &attr_newdir_in);
00453 
00454           update_flags = API_AddRegisterValues(cast64m(0),
00455                                                CORE_ATTR_ACCOUNT,
00456                                                CORE_ATTR_USER_PERMS,
00457                                                CORE_ATTR_GROUP_PERMS,
00458                                                CORE_ATTR_OTHER_PERMS, -1);
00459 
00460 #if defined(API_DMAP_GATEWAY)
00461 
00462           /*
00463            * If the gateway is trying to create a directory on a
00464            * mirrored fileset, it must supply a UID & GID for
00465            * the directory.
00466            */
00467 
00468           if(attr_parent.FilesetType == CORE_FS_TYPE_MIRRORED)
00469             {
00470               attr_newdir_in.UID = Ucred->SecPWent.Uid;
00471               attr_newdir_in.GID = Ucred->SecPWent.Gid;
00472               update_flags = API_AddRegisterValues(update_flags,
00473                                                    CORE_ATTR_UID, CORE_ATTR_GID, -1);
00474             }
00475 #endif
00476           /*
00477            * Note: The DM handle is not loaded here for non
00478            * HPSS filesets because the handle can only be
00479            * determined after the file is created on the
00480            * DMAP side. Therefore, the gateway must update
00481            * the directories attributes after the directory
00482            * is created.
00483            */
00484 
00485           error = API_core_MkDir(ThreadContext,
00486                                  rqstid,
00487                                  Ucred,
00488                                  &objhandle_parent,
00489                                  path_newdir,
00490                                  update_flags,
00491                                  &attr_newdir_in,
00492                                  select_flags, &attr_newdir_out, &objhandle_newdir);
00493 
00494           if(error != 0)
00495             {
00496               API_DEBUG_FPRINTF(DebugFile, &rqstid,
00497                                 "%s: Could not create directory"
00498                                 ", error=%d\n", function_name, error);
00499 
00500               API_LogMsg(function_name, rqstid, CS_DEBUG,
00501                          SOFTWARE_ERROR, NONE, API_REQUEST_ERROR, error);
00502             }
00503 #if HPSS_MAJOR_VERSION < 7
00504           break;
00505 
00506         default:
00507           if(error == 0)
00508             error = EIO;
00509           API_DEBUG_FPRINTF(DebugFile, &rqstid,
00510                             "%s: Bad case from DetermineCall().\n", function_name);
00511           break;
00512         }                       /* end switch */
00513 #endif
00514 
00515     }
00516 
00517   /* end (if error == 0) */
00518   /*
00519    *  Convert the returned attributes, if necessary.
00520    */
00521   if(RetAttrs != (hpss_Attrs_t *) NULL)
00522     {
00523       *RetAttrs = attr_newdir_out;
00524     }
00525 
00526   if(RetObjHandle != (ns_ObjHandle_t *) NULL)
00527     *RetObjHandle = objhandle_newdir;
00528 
00529   free(path_newdir);
00530   free(path_parent);
00531 
00532   return (error);
00533 }