nfs-ganesha 1.4

fsal_xattrs.c

Go to the documentation of this file.
00001 
00009 #ifdef HAVE_CONFIG_H
00010 #include "config.h"
00011 #endif
00012 
00013 #include "fsal.h"
00014 #include "fsal_internal.h"
00015 #include "fsal_convert.h"
00016 #include "HPSSclapiExt/hpssclapiext.h"
00017 
00018 #include <hpss_uuid.h>
00019 #include <hpss_errno.h>
00020 #include <hpss_limits.h>
00021 
00022 #if HPSS_LEVEL >= 730
00023 #include <hpss_xml.h>
00024 #endif
00025 
00026 /* generic definitions for extended attributes */
00027 
00028 #define XATTR_FOR_FILE     0x00000001
00029 #define XATTR_FOR_DIR      0x00000002
00030 #define XATTR_FOR_SYMLINK  0x00000004
00031 #define XATTR_FOR_ALL      0x0000000F
00032 #define XATTR_RO           0x00000100
00033 #define XATTR_RW           0x00000200
00034 
00035 /* function for getting an attribute value */
00036 
00037 typedef int (*xattr_getfunc_t) (hpssfsal_handle_t *,    /* object handle */
00038                                 hpssfsal_op_context_t *,        /* context */
00039                                 caddr_t,        /* output buff */
00040                                 size_t, /* output buff size */
00041                                 size_t *);      /* output size */
00042 
00043 typedef int (*xattr_setfunc_t) (hpssfsal_handle_t *,    /* object handle */
00044                                 hpssfsal_op_context_t *,        /* context */
00045                                 caddr_t,        /* input buff */
00046                                 size_t, /* input size */
00047                                 int);   /* creation flag */
00048 
00049 typedef int (*xattr_printfunc_t) (caddr_t,      /* Input buffer */
00050                                   size_t,       /* Input size   */
00051                                   caddr_t,      /* Output (ASCII) buffer */
00052                                   size_t *);    /* Output size */
00053 
00054 typedef struct fsal_xattr_def__
00055 {
00056   char xattr_name[FSAL_MAX_NAME_LEN];
00057   xattr_getfunc_t get_func;
00058   xattr_setfunc_t set_func;
00059   xattr_printfunc_t print_func;
00060   int flags;
00061 } fsal_xattr_def_t;
00062 
00063 /*
00064  * function for getting extended attributes for HPSS
00065  */
00066 
00067 /* Class of service */
00068 int get_file_cos(hpssfsal_handle_t * p_objecthandle,    /* IN */
00069                  hpssfsal_op_context_t * p_context,     /* IN */
00070                  caddr_t buffer_addr,   /* IN/OUT */
00071                  size_t buffer_size,    /* IN */
00072                  size_t * p_output_size)        /* OUT */
00073 {
00074   int rc;
00075   ns_ObjHandle_t hpss_hdl;
00076   hpss_Attrs_t hpss_attr;
00077 
00078   if(!p_objecthandle || !p_context || !p_output_size)
00079     return ERR_FSAL_FAULT;
00080 
00081   /* get attributes */
00082   /* We use  HPSSFSAL_GetRawAttrHandle for not chasing junctions
00083    * nor solving symlinks. What's more, we want hpss_Attrs_t.
00084    */
00085 
00086   TakeTokenFSCall();
00087 
00088   rc = HPSSFSAL_GetRawAttrHandle(&(p_objecthandle->data.ns_handle), NULL, &p_context->credential.hpss_usercred, FALSE,       /* don't solve junctions */
00089                                  &hpss_hdl, NULL, &hpss_attr);
00090 
00091   ReleaseTokenFSCall();
00092 
00093   /* The HPSS_ENOENT error actually means that handle is STALE */
00094   if(rc == HPSS_ENOENT)
00095     return ERR_FSAL_STALE;
00096   else if(rc)
00097     return hpss2fsal_error(rc);
00098 
00099   /* then store cos id in the output buffer */
00100 
00101   if(buffer_size < sizeof(hpss_attr.COSId))
00102     return ERR_FSAL_TOOSMALL;
00103 
00104   memcpy(buffer_addr, &hpss_attr.COSId, sizeof(hpss_attr.COSId));
00105 
00106   *p_output_size = sizeof(hpss_attr.COSId);
00107 
00108   return 0;
00109 
00110 }
00111 
00112 int print_file_cos(caddr_t InBuff, size_t InSize, caddr_t OutBuff, size_t * pOutSize)
00113 {
00114   unsigned int cosid = 0;
00115 
00116   memcpy((char *)&cosid, InBuff, sizeof(cosid));
00117 
00118   *pOutSize = snprintf(OutBuff, *pOutSize, "%u\n", cosid);
00119   return 0;
00120 }                               /* print_file_cos */
00121 
00122 /* Storage levels */
00123 int get_file_slevel(hpssfsal_handle_t * p_objecthandle, /* IN */
00124                     hpssfsal_op_context_t * p_context,  /* IN */
00125                     caddr_t buffer_addr,        /* IN/OUT */
00126                     size_t buffer_size, /* IN */
00127                     size_t * p_output_size)     /* OUT */
00128 {
00129   int rc, i;
00130   hpss_xfileattr_t hpss_xattr;
00131   char tmpstr[1024];
00132   char *outbuff;
00133   unsigned int index;
00134 
00135   if(!p_objecthandle || !p_context || !p_output_size)
00136     return ERR_FSAL_FAULT;
00137 
00138   /* get storage info */
00139 
00140   TakeTokenFSCall();
00141 
00142 #if HPSS_LEVEL < 622
00143   rc = HPSSFSAL_FileGetXAttributesHandle(&(p_objecthandle->data.ns_handle),
00144                                          API_GET_STATS_FOR_ALL_LEVELS, 0, &hpss_xattr);
00145 #elif HPSS_LEVEL == 622
00146   rc = hpss_FileGetXAttributesHandle(&(p_objecthandle->data.ns_handle),
00147                                      NULL,
00148                                      &(p_context->credential.hpss_usercred),
00149                                      API_GET_STATS_FOR_ALL_LEVELS, 0, NULL, &hpss_xattr);
00150 #elif HPSS_MAJOR_VERSION >= 7
00151   rc = hpss_FileGetXAttributesHandle(&(p_objecthandle->data.ns_handle),
00152                                      NULL,
00153                                      &(p_context->credential.hpss_usercred),
00154                                      API_GET_STATS_FOR_ALL_LEVELS, 0, &hpss_xattr);
00155 #endif
00156 
00157   ReleaseTokenFSCall();
00158 
00159   /* The HPSS_ENOENT error actually means that handle is STALE */
00160   if(rc == HPSS_ENOENT)
00161     return ERR_FSAL_STALE;
00162   else if(rc)
00163     return hpss2fsal_error(rc);
00164 
00165   /* now write info to buffer */
00166 
00167   outbuff = (char *)buffer_addr;
00168   outbuff[0] = '\0';
00169 
00170   for(index = 0; index < HPSS_MAX_STORAGE_LEVELS; index++)
00171     {
00172       if(hpss_xattr.SCAttrib[index].Flags == 0)
00173         continue;
00174 
00175       if(hpss_xattr.SCAttrib[index].Flags & BFS_BFATTRS_LEVEL_IS_DISK)
00176         snprintf(tmpstr, 1024, "Level %u (disk): %llu bytes\n", index,
00177                  hpss2fsal_64(hpss_xattr.SCAttrib[index].BytesAtLevel));
00178       else if(hpss_xattr.SCAttrib[index].Flags & BFS_BFATTRS_LEVEL_IS_TAPE)
00179         snprintf(tmpstr, 1024, "Level %u (tape): %llu bytes\n", index,
00180                  hpss2fsal_64(hpss_xattr.SCAttrib[index].BytesAtLevel));
00181       else
00182         snprintf(tmpstr, 1024, "Level %u: %llu bytes\n", index,
00183                  hpss2fsal_64(hpss_xattr.SCAttrib[index].BytesAtLevel));
00184 
00185       if(strlen(tmpstr) + strlen(outbuff) < buffer_size)
00186         strcat(outbuff, tmpstr);
00187       else
00188         break;
00189 
00190     }
00191 
00192     /* free the returned structure (Cf. HPSS ClAPI documentation) */
00193     for ( i = 0; i < HPSS_MAX_STORAGE_LEVELS; i++ )
00194     {
00195         int j;
00196         for ( j = 0; j < hpss_xattr.SCAttrib[i].NumberOfVVs; j++ )
00197         {
00198             if ( hpss_xattr.SCAttrib[i].VVAttrib[j].PVList != NULL )
00199             {
00200                 free( hpss_xattr.SCAttrib[i].VVAttrib[j].PVList );
00201             }
00202         }
00203     }
00204 
00205     *p_output_size = strlen(outbuff) + 1;
00206 
00207     return 0;
00208 }
00209 
00210 int print_ns_handle(caddr_t InBuff, size_t InSize, caddr_t OutBuff, size_t * pOutSize)
00211 {
00212   unsigned int i = 0;
00213   *pOutSize = 0;
00214 
00215   for(i = 0; i < InSize; i++)
00216     *pOutSize +=
00217         sprintf(&(((char *)OutBuff)[i * 2]), "%02x",
00218                 (unsigned char)(((char *)InBuff)[i]));
00219 
00220   ((char *)OutBuff)[*pOutSize] = '\n';
00221   *pOutSize += 1;
00222 
00223   return 0;
00224 }                               /* print_ns_handle */
00225 
00226 /* Namespace handle */
00227 int get_ns_handle(hpssfsal_handle_t * p_objecthandle,   /* IN */
00228                   hpssfsal_op_context_t * p_context,    /* IN */
00229                   caddr_t buffer_addr,  /* IN/OUT */
00230                   size_t buffer_size,   /* IN */
00231                   size_t * p_output_size)       /* OUT */
00232 {
00233 
00234   if(buffer_size > sizeof(ns_ObjHandle_t))
00235     {
00236       memcpy(buffer_addr, (caddr_t) & p_objecthandle->data.ns_handle, sizeof(ns_ObjHandle_t));
00237       *p_output_size = sizeof(ns_ObjHandle_t);
00238     }
00239   else
00240     {
00241       memcpy(buffer_addr, (caddr_t) & p_objecthandle->data.ns_handle, buffer_size);
00242       *p_output_size = buffer_size;
00243     }
00244 
00245   return 0;
00246 
00247 }
00248 
00249 /* Object type */
00250 int get_obj_type(hpssfsal_handle_t * p_objecthandle,    /* IN */
00251                  hpssfsal_op_context_t * p_context,     /* IN */
00252                  caddr_t buffer_addr,   /* IN/OUT */
00253                  size_t buffer_size,    /* IN */
00254                  size_t * p_output_size)        /* OUT */
00255 {
00256   switch (p_objecthandle->data.obj_type)
00257     {
00258     case FSAL_TYPE_DIR:
00259       strncpy((char *)buffer_addr, "directory", buffer_size);
00260       break;
00261 
00262     case FSAL_TYPE_FILE:
00263       strncpy((char *)buffer_addr, "file", buffer_size);
00264       break;
00265 
00266     case FSAL_TYPE_LNK:
00267       strncpy((char *)buffer_addr, "symlink", buffer_size);
00268       break;
00269 
00270     case FSAL_TYPE_JUNCTION:
00271       strncpy((char *)buffer_addr, "junction", buffer_size);
00272       break;
00273 
00274     default:
00275       strncpy((char *)buffer_addr, "other/unknown", buffer_size);
00276       break;
00277     }
00278   ((char *)buffer_addr)[strlen((char *)buffer_addr)] = '\n';
00279   *p_output_size = strlen((char *)buffer_addr) + 1;
00280   return 0;
00281 }
00282 
00283 /* Bitfile ID */
00284 int get_bfid(hpssfsal_handle_t * p_objecthandle,        /* IN */
00285              hpssfsal_op_context_t * p_context, /* IN */
00286              caddr_t buffer_addr,       /* IN/OUT */
00287              size_t buffer_size,        /* IN */
00288              size_t * p_output_size)    /* OUT */
00289 {
00290   int rc;
00291   ns_ObjHandle_t hpss_hdl;
00292   hpss_Attrs_t hpss_attr;
00293   char *tmp_str_uuid;
00294 
00295   if((rc = HPSSFSAL_GetRawAttrHandle(&(p_objecthandle->data.ns_handle),
00296                                      NULL,
00297                                      &(p_context->credential.hpss_usercred),
00298                                      FALSE, &hpss_hdl, NULL, &hpss_attr)) != 0)
00299     {
00300       return hpss2fsal_error(rc);
00301     }
00302 
00303   uuid_to_string(&(hpss_attr.BitfileId.ObjectID), (char **)&tmp_str_uuid, &rc);
00304   if(rc != 0)
00305     {
00306       return hpss2fsal_error(rc);
00307     }
00308 
00309   strncpy((char *)buffer_addr, tmp_str_uuid, buffer_size);
00310   *p_output_size = strlen((char *)buffer_addr) + 1;
00311 
00312   /* HPSS returns a string that it has just allocated.
00313    * Free it to avoid memory leak.
00314    */
00315   free(tmp_str_uuid);
00316 
00317   return 0;
00318 }
00319 
00320 static fsal_xattr_def_t xattr_list[] = {
00321   /* for all kind of entries */
00322   {"ns_handle", get_ns_handle, NULL, print_ns_handle, XATTR_FOR_ALL | XATTR_RO},
00323   {"type", get_obj_type, NULL, NULL, XATTR_FOR_ALL | XATTR_RO},
00324 
00325   /* for files only */
00326   {"bitfile_id", get_bfid, NULL, NULL, XATTR_FOR_FILE | XATTR_RO},
00327   {"class_of_service", get_file_cos, NULL, print_file_cos, XATTR_FOR_FILE | XATTR_RO},
00328   {"storage_levels", get_file_slevel, NULL, NULL, XATTR_FOR_FILE | XATTR_RO}
00329 
00330 };
00331 
00332 #define XATTR_COUNT 5
00333 
00334 /* we assume that this number is < 254 */
00335 #if ( XATTR_COUNT > 254 )
00336 #error "ERROR: xattr count > 254"
00337 #endif
00338 
00339 /* test if an object has a given attribute */
00340 static int do_match_type(int xattr_flag, fsal_nodetype_t obj_type)
00341 {
00342   switch (obj_type)
00343     {
00344     case FSAL_TYPE_FILE:
00345       return ((xattr_flag & XATTR_FOR_FILE) == XATTR_FOR_FILE);
00346 
00347     case FSAL_TYPE_DIR:
00348       return ((xattr_flag & XATTR_FOR_DIR) == XATTR_FOR_DIR);
00349 
00350     case FSAL_TYPE_LNK:
00351       return ((xattr_flag & XATTR_FOR_SYMLINK) == XATTR_FOR_SYMLINK);
00352 
00353     default:
00354       return ((xattr_flag & XATTR_FOR_ALL) == XATTR_FOR_ALL);
00355     }
00356 }
00357 
00358 static int attr_is_read_only(unsigned int attr_index)
00359 {
00360   if(attr_index < XATTR_COUNT)
00361     {
00362       if(xattr_list[attr_index].flags & XATTR_RO)
00363         return TRUE;
00364     }
00365   /* else : UDA */
00366   return FALSE;
00367 }
00368 
00369 static int file_attributes_to_xattr_attrs(fsal_attrib_list_t * file_attrs,
00370                                           fsal_attrib_list_t * p_xattr_attrs,
00371                                           unsigned int attr_index)
00372 {
00373 
00374   /* supported attributes are:
00375    * - owner (same as the objet)
00376    * - group (same as the objet)
00377    * - type FSAL_TYPE_XATTR
00378    * - fileid (attr index ? or (fileid^((index+1)<<24)) )
00379    * - mode (config & file)
00380    * - atime, mtime, ctime = these of the object ?
00381    * - size=1block, used=1block
00382    * - rdev=0
00383    * - nlink=1
00384    */
00385   fsal_attrib_mask_t supported = FSAL_ATTR_SUPPATTR | FSAL_ATTR_MODE | FSAL_ATTR_FILEID
00386       | FSAL_ATTR_TYPE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP
00387       | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME
00388       | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_SIZE
00389       | FSAL_ATTR_SPACEUSED | FSAL_ATTR_NUMLINKS | FSAL_ATTR_RAWDEV | FSAL_ATTR_FSID;
00390   fsal_attrib_mask_t unsupp;
00391 
00392   /* only those supported by filesystem */
00393   supported &= global_fs_info.supported_attrs;
00394 
00395   if(p_xattr_attrs->asked_attributes == 0)
00396     {
00397       p_xattr_attrs->asked_attributes = supported;
00398 
00399       LogCrit(COMPONENT_FSAL,
00400                         "Error: p_xattr_attrs->asked_attributes was 0 in %s() line %d, file %s",
00401                         __FUNCTION__, __LINE__, __FILE__);
00402     }
00403 
00404   unsupp = p_xattr_attrs->asked_attributes & (~supported);
00405 
00406   if(unsupp)
00407     {
00408       LogDebug(COMPONENT_FSAL,
00409                         "Asking for unsupported attributes in %s(): %#llX removing it from asked attributes",
00410                         __FUNCTION__, unsupp);
00411 
00412       p_xattr_attrs->asked_attributes &= (~unsupp);
00413     }
00414 
00415   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SUPPATTR)
00416     p_xattr_attrs->supported_attributes = supported;
00417 
00418   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE)
00419     {
00420       p_xattr_attrs->mode = file_attrs->mode & global_fs_info.xattr_access_rights;
00421 
00422       if(attr_is_read_only(attr_index))
00423         p_xattr_attrs->mode &= ~(0222);
00424     }
00425 
00426   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FILEID)
00427     {
00428       unsigned int i;
00429       unsigned long hash = attr_index + 1;
00430       char *str = (char *)&file_attrs->fileid;
00431 
00432       for(i = 0; i < sizeof(p_xattr_attrs->fileid); i++, str++)
00433         {
00434           hash = (hash << 5) - hash + (unsigned long)(*str);
00435         }
00436       p_xattr_attrs->fileid = hash;
00437     }
00438 
00439   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_TYPE)
00440     p_xattr_attrs->type = FSAL_TYPE_XATTR;
00441 
00442   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00443     p_xattr_attrs->owner = file_attrs->owner;
00444 
00445   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_GROUP)
00446     p_xattr_attrs->group = file_attrs->group;
00447 
00448   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_ATIME)
00449     p_xattr_attrs->atime = file_attrs->atime;
00450 
00451   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MTIME)
00452     p_xattr_attrs->mtime = file_attrs->mtime;
00453 
00454   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CTIME)
00455     p_xattr_attrs->ctime = file_attrs->ctime;
00456 
00457   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CREATION)
00458     p_xattr_attrs->creation = file_attrs->creation;
00459 
00460   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CHGTIME)
00461     {
00462       p_xattr_attrs->chgtime = file_attrs->chgtime;
00463       p_xattr_attrs->change = (uint64_t) p_xattr_attrs->chgtime.seconds;
00464     }
00465 
00466   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SIZE)
00467     p_xattr_attrs->filesize = DEV_BSIZE;
00468 
00469   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SPACEUSED)
00470     p_xattr_attrs->spaceused = DEV_BSIZE;
00471 
00472   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_NUMLINKS)
00473     p_xattr_attrs->numlinks = 1;
00474 
00475   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_RAWDEV)
00476     {
00477       p_xattr_attrs->rawdev.major = 0;
00478       p_xattr_attrs->rawdev.minor = 0;
00479     }
00480 
00481   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FSID)
00482     {
00483       p_xattr_attrs->fsid = file_attrs->fsid;
00484     }
00485 
00486   /* if mode==0, then owner is set to root and mode is set to 0600 */
00487   if((p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00488      && (p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE) && (p_xattr_attrs->mode == 0))
00489     {
00490       p_xattr_attrs->owner = 0;
00491       p_xattr_attrs->mode = 0600;
00492       if(attr_is_read_only(attr_index))
00493         p_xattr_attrs->mode &= ~(0200);
00494     }
00495 
00496   return 0;
00497 
00498 }
00499 
00508 fsal_status_t HPSSFSAL_GetXAttrAttrs(hpssfsal_handle_t * p_objecthandle,        /* IN */
00509                                      hpssfsal_op_context_t * p_context, /* IN */
00510                                      unsigned int xattr_id,     /* IN */
00511                                      fsal_attrib_list_t * p_attrs
00513     )
00514 {
00515   int rc;
00516   char buff[MAXNAMLEN];
00517   fsal_status_t st;
00518   fsal_attrib_list_t file_attrs;
00519 
00520   /* sanity checks */
00521   if(!p_objecthandle || !p_context || !p_attrs)
00522     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrAttrs);
00523 
00524   /* check that this index match the type of entry */
00525   if(xattr_id < XATTR_COUNT
00526      && !do_match_type(xattr_list[xattr_id].flags, p_objecthandle->data.obj_type))
00527     {
00528       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrAttrs);
00529     }
00530   else if(xattr_id >= XATTR_COUNT)
00531     {
00532       /* This is UDA */
00533       LogFullDebug(COMPONENT_FSAL, "Getting attributes for UDA #%u",
00534                         xattr_id - XATTR_COUNT);
00535     }
00536 
00537   /* object attributes we want to retrieve from parent */
00538   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00539       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME
00540       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00541 
00542   /* don't retrieve attributes not asked */
00543 
00544   file_attrs.asked_attributes &= p_attrs->asked_attributes;
00545 
00546   st = HPSSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00547 
00548   if(FSAL_IS_ERROR(st))
00549     Return(st.major, st.minor, INDEX_FSAL_GetXAttrAttrs);
00550 
00551   if((rc = file_attributes_to_xattr_attrs(&file_attrs, p_attrs, xattr_id)))
00552     {
00553       Return(ERR_FSAL_INVAL, rc, INDEX_FSAL_GetXAttrAttrs);
00554     }
00555 
00556   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrAttrs);
00557 
00558 }                               /* FSAL_GetXAttrAttrs */
00559 
00560 static int hpss_uda_name_2_fsal(const char *src, char *out)
00561 {
00562   const char *curr_src = src;
00563   char *curr = out;
00564 
00565   /* skip first '/' */
00566   while((*curr_src == '/') && (*curr_src != '\0'))
00567     curr_src++;
00568   if(*curr_src == '\0')
00569     return ERR_FSAL_INVAL;
00570 
00571   strcpy(curr, curr_src);
00572   while((curr = strchr(out, '/')) != NULL)
00573     {
00574       *curr = '.';
00575     }
00576   return 0;
00577 }
00578 
00579 static int fsal_xattr_name_2_uda(const char *src, char *out)
00580 {
00581   char *curr = out;
00582 
00583   /* add first / */
00584   *curr = '/';
00585   curr++;
00586 
00587   /* copy the xattr name */
00588   strcpy(curr, src);
00589 
00590   /* then replace '.' with '/' */
00591   while((curr = strchr(out, '.')) != NULL)
00592     {
00593       *curr = '/';
00594     }
00595 
00596   /* UDA path must start with '/hpss/' */
00597   if(strncmp(out, "/hpss/", 6) != 0)
00598     return ERR_FSAL_INVAL;
00599 
00600   return 0;
00601 }
00602 
00615 fsal_status_t HPSSFSAL_ListXAttrs(hpssfsal_handle_t * p_objecthandle,   /* IN */
00616                                   unsigned int argcookie,  /* IN */
00617                                   hpssfsal_op_context_t * p_context,    /* IN */
00618                                   fsal_xattrent_t * xattrs_tab, /* IN/OUT */
00619                                   unsigned int xattrs_tabsize,  /* IN */
00620                                   unsigned int *p_nb_returned,  /* OUT */
00621                                   int *end_of_list      /* OUT */
00622     )
00623 {
00624   unsigned int index;
00625   unsigned int out_index;
00626   fsal_status_t st;
00627   fsal_attrib_list_t file_attrs;
00628   int rc;
00629   unsigned int cookie = argcookie ;
00630 
00631   /* sanity checks */
00632   if(!p_objecthandle || !p_context || !xattrs_tab || !p_nb_returned || !end_of_list)
00633     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_ListXAttrs);
00634 
00635   /* Deal with special cookie */
00636   if( argcookie == FSAL_XATTR_RW_COOKIE ) cookie = XATTR_COUNT ;
00637 
00638   /* object attributes we want to retrieve from parent */
00639   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00640       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME
00641       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00642 
00643   /* don't retrieve unsuipported attributes */
00644   file_attrs.asked_attributes &= global_fs_info.supported_attrs;
00645 
00646   st = FSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00647 
00648   if(FSAL_IS_ERROR(st))
00649     Return(st.major, st.minor, INDEX_FSAL_ListXAttrs);
00650 
00651   for(index = cookie, out_index = 0;
00652       index < XATTR_COUNT && out_index < xattrs_tabsize; index++)
00653     {
00654       if(do_match_type(xattr_list[index].flags, p_objecthandle->data.obj_type))
00655         {
00656 
00657           /* fills an xattr entry */
00658           xattrs_tab[out_index].xattr_id = index;
00659           FSAL_str2name(xattr_list[index].xattr_name, FSAL_MAX_NAME_LEN,
00660                         &xattrs_tab[out_index].xattr_name);
00661           xattrs_tab[out_index].xattr_cookie = index + 1;
00662 
00663           /* set asked attributes (all supported) */
00664           xattrs_tab[out_index].attributes.asked_attributes =
00665               global_fs_info.supported_attrs;
00666 
00667           rc = file_attributes_to_xattr_attrs(&file_attrs,
00668                                               &xattrs_tab[out_index].attributes, index);
00669 
00670           if(rc != 0)
00671             {
00672               /* set error flag */
00673               LogDebug(COMPONENT_FSAL,
00674                                 "Error %d getting attributes for xattr '%s'", rc,
00675                                 xattrs_tab[out_index].xattr_name);
00676               xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00677             }
00678 
00679           /* next output slot */
00680           out_index++;
00681         }
00682     }
00683 
00684   *end_of_list = (index == XATTR_COUNT);
00685 
00686 #if HPSS_LEVEL >= 730
00687   {
00688     /* save a call if output array is full */
00689     if(out_index == xattrs_tabsize)
00690       {
00691         *end_of_list = FALSE;
00692         *p_nb_returned = out_index;
00693         Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00694       }
00695 
00696     /* get list of UDAs for this entry */
00697     hpss_userattr_list_t attr_list;
00698 
00699     memset(&attr_list, 0, sizeof(hpss_userattr_list_t));
00700 
00701     TakeTokenFSCall();
00702     rc = hpss_UserAttrListAttrHandle(&(p_objecthandle->data.ns_handle),
00703                                      NULL,
00704                                      &(p_context->credential.hpss_usercred),
00705                                      &attr_list, XML_ATTR);
00706     ReleaseTokenFSCall();
00707 
00708     if(rc == 0)
00709       {
00710         unsigned int i;
00711         for(i = 0; (i < attr_list.len) && (out_index < xattrs_tabsize); i++)
00712           {
00713             char attr_name[FSAL_MAX_NAME_LEN];
00714 
00715             /* the id is XATTR_COUNT + index of HPSS UDA */
00716             index = XATTR_COUNT + i;
00717 
00718             /* continue while index < cookie */
00719             if(index < cookie)
00720               continue;
00721 
00722             xattrs_tab[out_index].xattr_id = index;
00723 
00724             if(strlen(attr_list.Pair[i].Key) >= FSAL_MAX_NAME_LEN)
00725               Return(ERR_FSAL_NAMETOOLONG, 0, INDEX_FSAL_ListXAttrs);
00726 
00727             /* HPSS UDAs namespace is slash-separated.
00728              * we convert '/' to '.'
00729              */
00730             rc = hpss_uda_name_2_fsal(attr_list.Pair[i].Key, attr_name);
00731 
00732             if(rc != ERR_FSAL_NO_ERROR)
00733               Return(rc, 0, INDEX_FSAL_ListXAttrs);
00734 
00735             FSAL_str2name(attr_name, FSAL_MAX_NAME_LEN,
00736                           &xattrs_tab[out_index].xattr_name);
00737             xattrs_tab[out_index].xattr_cookie = index + 1;
00738 
00739             /* set asked attributes (all supported) */
00740             xattrs_tab[out_index].attributes.asked_attributes =
00741                 global_fs_info.supported_attrs;
00742 
00743             rc = file_attributes_to_xattr_attrs(&file_attrs,
00744                                                 &xattrs_tab[out_index].attributes, index);
00745             if(rc != 0)
00746               {
00747                 /* set error flag */
00748                 LogDebug(COMPONENT_FSAL,
00749                                   "Error %d getting attributes for xattr \'%s\'", rc,
00750                                   xattrs_tab[out_index].xattr_name);
00751                 xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00752               }
00753             /* we know the size here (+2 for \n\0) */
00754             else if(attr_list.Pair[i].Value != NULL)
00755               xattrs_tab[out_index].attributes.filesize
00756                   = strlen(attr_list.Pair[i].Value) + 2;
00757 
00758             /* next output slot */
00759             out_index++;
00760           }
00761         /* not end of list if there is more UDAs */
00762         if(i < attr_list.len)
00763           *end_of_list = FALSE;
00764         else
00765           *end_of_list = TRUE;
00766       }
00767   }
00768 
00769 #endif
00770 
00771   *p_nb_returned = out_index;
00772 
00773   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00774 
00775 }
00776 
00787 fsal_status_t HPSSFSAL_GetXAttrValueById(hpssfsal_handle_t * p_objecthandle,    /* IN */
00788                                          unsigned int xattr_id, /* IN */
00789                                          hpssfsal_op_context_t * p_context,     /* IN */
00790                                          caddr_t buffer_addr,   /* IN/OUT */
00791                                          size_t buffer_size,    /* IN */
00792                                          size_t * p_output_size /* OUT */
00793     )
00794 {
00795   int rc;
00796   char buff[MAXNAMLEN];
00797 
00798   /* sanity checks */
00799   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr)
00800     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00801 
00802   /* check that this index match the type of entry */
00803   if(xattr_id < XATTR_COUNT
00804      && !do_match_type(xattr_list[xattr_id].flags, p_objecthandle->data.obj_type))
00805     {
00806       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue);
00807     }
00808   else if(xattr_id >= XATTR_COUNT)
00809     {
00810 #if HPSS_LEVEL >= 730
00811       /* This is a UDA */
00812       hpss_userattr_list_t attr_list;
00813       unsigned int i;
00814       memset(&attr_list, 0, sizeof(hpss_userattr_list_t));
00815 
00816       LogFullDebug(COMPONENT_FSAL, "Getting value for UDA #%u",
00817                         xattr_id - XATTR_COUNT);
00818 
00819       /* get list of UDAs for this entry, and return the good value */
00820 
00821       TakeTokenFSCall();
00822       rc = hpss_UserAttrListAttrHandle(&(p_objecthandle->data.ns_handle),
00823                                        NULL,
00824                                        &(p_context->credential.hpss_usercred),
00825                                        &attr_list, XML_ATTR);
00826       ReleaseTokenFSCall();
00827 
00828       if(rc != 0)
00829         Return(hpss2fsal_error(rc), rc, INDEX_FSAL_GetXAttrValue);
00830       else if(xattr_id - XATTR_COUNT >= attr_list.len)
00831         /* this xattr does not exist anymore */
00832         Return(ERR_FSAL_STALE, 0, INDEX_FSAL_GetXAttrValue);
00833 
00834       if((attr_list.Pair[xattr_id - XATTR_COUNT].Value != NULL)
00835          && (attr_list.Pair[xattr_id - XATTR_COUNT].Value[0] != '\0'))
00836         snprintf((char *)buffer_addr, buffer_size, "%s\n",
00837                  attr_list.Pair[xattr_id - XATTR_COUNT].Value);
00838       else
00839         strcpy((char *)buffer_addr, "");
00840 
00841       *p_output_size = strlen((char *)buffer_addr) + 1;
00842 
00843       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00844 
00845 #else
00846       /* udas are not supported. xattr_id is too high. */
00847       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue);
00848 #endif
00849     }
00850 
00851   /* get the value */
00852 
00853   if(xattr_list[xattr_id].print_func == NULL)
00854     {
00855       rc = xattr_list[xattr_id].get_func(p_objecthandle,
00856                                          p_context,
00857                                          buffer_addr, buffer_size, p_output_size);
00858     }
00859   else
00860     {
00861       rc = xattr_list[xattr_id].get_func(p_objecthandle,
00862                                          p_context, buff, MAXNAMLEN, p_output_size);
00863 
00864       xattr_list[xattr_id].print_func(buff, MAXNAMLEN, buffer_addr, p_output_size);
00865     }
00866 
00867   Return(rc, 0, INDEX_FSAL_GetXAttrValue);
00868 
00869 }
00870 
00880 fsal_status_t HPSSFSAL_GetXAttrIdByName(hpssfsal_handle_t * p_objecthandle,     /* IN */
00881                                         const fsal_name_t * xattr_name, /* IN */
00882                                         hpssfsal_op_context_t * p_context,      /* IN */
00883                                         unsigned int *pxattr_id /* OUT */
00884     )
00885 {
00886   unsigned int index, i;
00887   int found = FALSE;
00888 
00889   /* sanity checks */
00890   if(!p_objecthandle || !xattr_name)
00891     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00892 
00893   for(index = 0; index < XATTR_COUNT; index++)
00894     {
00895       if(do_match_type(xattr_list[index].flags, p_objecthandle->data.obj_type)
00896          && !strcmp(xattr_list[index].xattr_name, xattr_name->name))
00897         {
00898           found = TRUE;
00899           break;
00900         }
00901     }
00902 
00903 #if HPSS_LEVEL >= 730
00904   if(!found)
00905     {
00906       /* search for name in UDAs */
00907       hpss_userattr_list_t attr_list;
00908       unsigned int i;
00909       int rc;
00910       char attrpath[FSAL_MAX_NAME_LEN];
00911 
00912       /* convert FSAL xattr name to HPSS attr path.
00913        * returns error if it is not a UDA name.
00914        */
00915       if(fsal_xattr_name_2_uda(xattr_name->name, attrpath) == 0)
00916         {
00917 
00918           memset(&attr_list, 0, sizeof(hpss_userattr_list_t));
00919 
00920           LogFullDebug(COMPONENT_FSAL, "looking for xattr '%s' in UDAs",
00921                             xattr_name->name);
00922 
00923           /* get list of UDAs for this entry, and return the good index */
00924 
00925           TakeTokenFSCall();
00926           rc = hpss_UserAttrListAttrHandle(&(p_objecthandle->data.ns_handle),
00927                                            NULL,
00928                                            &(p_context->credential.hpss_usercred),
00929                                            &attr_list, XML_ATTR);
00930           ReleaseTokenFSCall();
00931 
00932           if(rc == 0)
00933             {
00934 
00935               for(i = 0; i < attr_list.len; i++)
00936                 {
00937                   if(!strcmp(attr_list.Pair[i].Key, attrpath))
00938                     {
00939                       /* xattr index is XATTR_COUNT + UDA index */
00940                       index = XATTR_COUNT + i;
00941                       found = TRUE;
00942                       break;
00943                     }
00944                 }
00945             }
00946 
00947         }
00948       /* enf if valid UDA name */
00949     }                           /* end if not found */
00950 #endif
00951 
00952   if(found)
00953     {
00954       *pxattr_id = index;
00955       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00956     }
00957   else
00958     Return(ERR_FSAL_NOENT, ENOENT, INDEX_FSAL_GetXAttrValue);
00959 }                               /* FSAL_GetXAttrIdByName */
00960 
00971 fsal_status_t HPSSFSAL_GetXAttrValueByName(hpssfsal_handle_t * p_objecthandle,  /* IN */
00972                                            const fsal_name_t * xattr_name,      /* IN */
00973                                            hpssfsal_op_context_t * p_context,   /* IN */
00974                                            caddr_t buffer_addr, /* IN/OUT */
00975                                            size_t buffer_size,  /* IN */
00976                                            size_t * p_output_size       /* OUT */
00977     )
00978 {
00979   unsigned int index;
00980   fsal_status_t st;
00981 #if HPSS_LEVEL >= 730
00982   char attrpath[MAXPATHLEN];
00983   char attrval[MAXPATHLEN];
00984   int rc;
00985 #endif
00986 
00987   /* sanity checks */
00988   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name)
00989     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00990 
00991   /* look for this name */
00992 
00993   for(index = 0; index < XATTR_COUNT; index++)
00994     {
00995       if(do_match_type(xattr_list[index].flags, p_objecthandle->data.obj_type)
00996          && !strcmp(xattr_list[index].xattr_name, xattr_name->name))
00997         {
00998 
00999           return FSAL_GetXAttrValueById(p_objecthandle, index, p_context,
01000                                         buffer_addr, buffer_size, p_output_size);
01001 
01002         }
01003     }
01004 
01005 #if HPSS_LEVEL >= 730
01006   if(fsal_xattr_name_2_uda(xattr_name->name, attrpath) == 0)
01007     {
01008       /* get uda value */
01009       hpss_userattr_list_t attr;
01010 
01011       attr.len = 1;
01012       /* use malloc because HPSS may free it */
01013       attr.Pair = malloc(sizeof(hpss_userattr_t));
01014       if(attr.Pair == NULL)
01015         Return(ERR_FSAL_NOMEM, errno, INDEX_FSAL_GetXAttrValue);
01016 
01017       attr.Pair[0].Key = attrpath;
01018       attr.Pair[0].Value = attrval;
01019 
01020       rc = hpss_UserAttrGetAttrHandle(&(p_objecthandle->data.ns_handle),
01021                                       NULL, &(p_context->credential.hpss_usercred),
01022                                       &attr, UDA_API_VALUE);
01023       if(rc)
01024         {
01025           free(attr.Pair);
01026           Return(hpss2fsal_error(rc), rc, INDEX_FSAL_GetXAttrValue);
01027         }
01028 
01029       if(attr.len > 0)
01030         {
01031           if(attr.Pair[0].Value != NULL)
01032             {
01033               char *noxml = hpss_ChompXMLHeader(attr.Pair[0].Value, NULL);
01034               strcpy(attrval, noxml);
01035               free(noxml);
01036               strncpy((char *)buffer_addr, attrval, buffer_size);
01037               *p_output_size = strlen(attrval) + 1;
01038             }
01039           else
01040             {
01041               strcpy((char *)buffer_addr, "");
01042               *p_output_size = 1;
01043             }
01044 
01045           free(attr.Pair);
01046           Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
01047         }
01048       else
01049         {
01050           free(attr.Pair);
01051           Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue);
01052         }
01053     }
01054 #endif
01055 
01056   /* not found */
01057   Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue);
01058 
01059 }
01060 
01061 static void chomp_attr_value(char *str, size_t size)
01062 {
01063   int len;
01064 
01065   if(str == NULL)
01066     return;
01067 
01068   /* security: set last char to '\0' */
01069   str[size - 1] = '\0';
01070 
01071   len = strnlen(str, size);
01072   if((len > 0) && (str[len - 1] == '\n'))
01073     str[len - 1] = '\0';
01074 }
01075 
01076 fsal_status_t HPSSFSAL_SetXAttrValue(hpssfsal_handle_t * p_objecthandle,        /* IN */
01077                                      const fsal_name_t * xattr_name,    /* IN */
01078                                      hpssfsal_op_context_t * p_context, /* IN */
01079                                      caddr_t buffer_addr,       /* IN */
01080                                      size_t buffer_size,        /* IN */
01081                                      int create /* IN */
01082     )
01083 {
01084 #if HPSS_LEVEL >= 730
01085   int rc;
01086   char attrpath[FSAL_MAX_NAME_LEN];
01087   hpss_userattr_list_t inAttr;
01088 
01089   /* check that UDA name is valid */
01090   if(fsal_xattr_name_2_uda(xattr_name->name, attrpath) != 0)
01091     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_SetXAttrValue);
01092 
01093   /* remove '\n" */
01094   chomp_attr_value((char *)buffer_addr, buffer_size);
01095 
01096   /* Set the UDA value */
01097 
01098   inAttr.len = 1;
01099   /* must use malloc()  here, because hpss clapi may free() it */
01100   inAttr.Pair = malloc(inAttr.len * sizeof(hpss_userattr_t));
01101   inAttr.Pair[0].Key = attrpath;
01102   inAttr.Pair[0].Value = (char *)buffer_addr;
01103 
01104   TakeTokenFSCall();
01105   rc = hpss_UserAttrSetAttrHandle(&(p_objecthandle->data.ns_handle),
01106                                   NULL,
01107                                   &(p_context->credential.hpss_usercred), &inAttr, NULL);
01108   ReleaseTokenFSCall();
01109 
01110   free(inAttr.Pair);
01111 
01112   Return(hpss2fsal_error(rc), rc, INDEX_FSAL_SetXAttrValue);
01113 
01114 #else
01115   Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
01116 #endif
01117 }
01118 
01119 fsal_status_t HPSSFSAL_SetXAttrValueById(hpssfsal_handle_t * p_objecthandle,    /* IN */
01120                                          unsigned int xattr_id, /* IN */
01121                                          hpssfsal_op_context_t * p_context,     /* IN */
01122                                          caddr_t buffer_addr,   /* IN */
01123                                          size_t buffer_size     /* IN */
01124     )
01125 {
01126 #if HPSS_LEVEL >= 730
01127   hpss_userattr_list_t attr_list;
01128   hpss_userattr_list_t inAttr;
01129   unsigned int i;
01130   int rc;
01131 
01132   if(attr_is_read_only(xattr_id))
01133     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
01134   else if(xattr_id < XATTR_COUNT)
01135     /* this is not a UDA (setattr not supported) */
01136     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
01137 
01138   /* remove '\n" */
01139   chomp_attr_value((char *)buffer_addr, buffer_size);
01140 
01141   memset(&attr_list, 0, sizeof(hpss_userattr_list_t));
01142 
01143   LogFullDebug(COMPONENT_FSAL, "Getting name of UDA #%u",
01144                     xattr_id - XATTR_COUNT);
01145 
01146   TakeTokenFSCall();
01147   rc = hpss_UserAttrListAttrHandle(&(p_objecthandle->data.ns_handle),
01148                                    NULL,
01149                                    &(p_context->credential.hpss_usercred),
01150                                    &attr_list, XML_ATTR);
01151   ReleaseTokenFSCall();
01152 
01153   if(rc != 0)
01154     Return(hpss2fsal_error(rc), rc, INDEX_FSAL_SetXAttrValue);
01155   else if(xattr_id - XATTR_COUNT >= attr_list.len)
01156     /* this xattr does not exist anymore */
01157     Return(ERR_FSAL_STALE, 0, INDEX_FSAL_SetXAttrValue);
01158 
01159   /* set the UDA by its name */
01160 
01161   inAttr.len = 1;
01162   /* must use malloc()  here, because hpss clapi may free() it */
01163   inAttr.Pair = malloc(inAttr.len * sizeof(hpss_userattr_t));
01164   inAttr.Pair[0].Key = attr_list.Pair[xattr_id - XATTR_COUNT].Key;
01165   inAttr.Pair[0].Value = (char *)buffer_addr;
01166 
01167   TakeTokenFSCall();
01168   rc = hpss_UserAttrSetAttrHandle(&(p_objecthandle->data.ns_handle),
01169                                   NULL,
01170                                   &(p_context->credential.hpss_usercred), &inAttr, NULL);
01171   ReleaseTokenFSCall();
01172 
01173   free(inAttr.Pair);
01174 
01175   Return(hpss2fsal_error(rc), rc, INDEX_FSAL_SetXAttrValue);
01176 
01177 #else
01178   Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
01179 #endif
01180 }
01181 
01189 fsal_status_t HPSSFSAL_RemoveXAttrById(hpssfsal_handle_t * p_objecthandle,      /* IN */
01190                                        hpssfsal_op_context_t * p_context,       /* IN */
01191                                        unsigned int xattr_id)   /* IN */
01192 {
01193   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01194 }                               /* FSAL_RemoveXAttrById */
01195 
01203 fsal_status_t HPSSFSAL_RemoveXAttrByName(hpssfsal_handle_t * p_objecthandle,    /* IN */
01204                                          hpssfsal_op_context_t * p_context,     /* IN */
01205                                          const fsal_name_t * xattr_name)        /* IN */
01206 {
01207   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01208 }                               /* FSAL_RemoveXAttrById */
01209 
01210 int HPSSFSAL_GetXattrOffsetSetable( void )
01211 {
01212   return XATTR_COUNT ;
01213 }