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 "fsal_common.h"
00017 
00018 #include <string.h>
00019 
00020 /* generic definitions for extended attributes */
00021 
00022 #define XATTR_FOR_FILE     0x00000001
00023 #define XATTR_FOR_DIR      0x00000002
00024 #define XATTR_FOR_SYMLINK  0x00000004
00025 #define XATTR_FOR_ALL      0x0000000F
00026 #define XATTR_RO           0x00000100
00027 #define XATTR_RW           0x00000200
00028 
00029 /* function for getting an attribute value */
00030 
00031 typedef int (*xattr_getfunc_t) (zfsfsal_handle_t *,        /* object handle */
00032                                 zfsfsal_op_context_t *,    /* context */
00033                                 caddr_t,        /* output buff */
00034                                 size_t, /* output buff size */
00035                                 size_t *);      /* output size */
00036 
00037 typedef int (*xattr_setfunc_t) (zfsfsal_handle_t *,        /* object handle */
00038                                 zfsfsal_op_context_t *,    /* context */
00039                                 caddr_t,        /* input buff */
00040                                 size_t, /* input size */
00041                                 int);   /* creation flag */
00042 
00043 typedef int (*xattr_printfunc_t) (caddr_t,      /* Input buffer */
00044                                   size_t,       /* Input size   */
00045                                   caddr_t,      /* Output (ASCII) buffer */
00046                                   size_t *);    /* Output size */
00047 
00048 typedef struct fsal_xattr_def__
00049 {
00050   char xattr_name[FSAL_MAX_NAME_LEN];
00051   xattr_getfunc_t get_func;
00052   xattr_setfunc_t set_func;
00053   xattr_printfunc_t print_func;
00054   int flags;
00055 } fsal_xattr_def_t;
00056 
00057 /*
00058  * DEFINE HERE YOUR GET/SET FUNCTIONS
00059  */
00060 
00061 int get_generation(zfsfsal_handle_t * p_objecthandle,       /* IN */
00062                    zfsfsal_op_context_t * p_context,        /* IN */
00063                    caddr_t buffer_addr,  /* IN/OUT */
00064                    size_t buffer_size,   /* IN */
00065                    size_t * p_output_size)       /* OUT */
00066 {
00067   if(!p_objecthandle || !p_context || !p_output_size)
00068     return ERR_FSAL_FAULT;
00069 
00070   memcpy(buffer_addr, &p_objecthandle->data.zfs_handle.generation,
00071          sizeof(p_objecthandle->data.zfs_handle.generation));
00072   *p_output_size = sizeof(p_objecthandle->data.zfs_handle.generation);
00073 
00074   return 0;
00075 }
00076 
00077 int print_generation(caddr_t InBuff, size_t InSize, caddr_t OutBuff, size_t * pOutSize)
00078 {
00079   uint64_t generation;
00080 
00081   memcpy((char *)&generation, InBuff, sizeof(generation));
00082 
00083   *pOutSize = snprintf(OutBuff, *pOutSize, "%"PRIu64, generation);
00084 
00085   return 0;
00086 }
00087 
00088 /* DEFINE HERE YOUR ATTRIBUTES LIST */
00089 
00090 static fsal_xattr_def_t xattr_list[] = {
00091   {"generation", get_generation, NULL, print_generation, XATTR_FOR_ALL}// | XATTR_RO}
00092 };
00093 
00094 #define XATTR_COUNT 1
00095 
00096 /* we assume that this number is < 254 */
00097 #if ( XATTR_COUNT > 254 )
00098 #error "ERROR: xattr count > 254"
00099 #endif
00100 
00101 /* YOUR SHOULD NOT HAVE TO MODIFY THE FOLLOWING FUNCTIONS */
00102 
00103 /* test if an object has a given attribute */
00104 static int do_match_type(int xattr_flag, fsal_nodetype_t obj_type)
00105 {
00106   switch (obj_type)
00107     {
00108     case FSAL_TYPE_FILE:
00109       return ((xattr_flag & XATTR_FOR_FILE) == XATTR_FOR_FILE);
00110 
00111     case FSAL_TYPE_DIR:
00112       return ((xattr_flag & XATTR_FOR_DIR) == XATTR_FOR_DIR);
00113 
00114     case FSAL_TYPE_LNK:
00115       return ((xattr_flag & XATTR_FOR_SYMLINK) == XATTR_FOR_SYMLINK);
00116 
00117     default:
00118       return ((xattr_flag & XATTR_FOR_ALL) == XATTR_FOR_ALL);
00119     }
00120 }
00121 
00122 static int attr_is_read_only(unsigned int attr_index)
00123 {
00124   if(attr_index < XATTR_COUNT)
00125     {
00126       if(xattr_list[attr_index].flags & XATTR_RO)
00127         return TRUE;
00128     }
00129   /* else : standard xattr */
00130   return FALSE;
00131 }
00132 
00133 static int file_attributes_to_xattr_attrs(fsal_attrib_list_t * file_attrs,
00134                                           fsal_attrib_list_t * p_xattr_attrs,
00135                                           unsigned int attr_index)
00136 {
00137   /* supported attributes are:
00138    * - owner (same as the objet)
00139    * - group (same as the objet)
00140    * - type FSAL_TYPE_XATTR
00141    * - fileid (attr index ? or (fileid^((index+1)<<24)) )
00142    * - mode (config & file)
00143    * - atime, mtime, ctime = these of the object ?
00144    * - size=1block, used=1block
00145    * - rdev=0
00146    * - nlink=1
00147    */
00148   fsal_attrib_mask_t supported = FSAL_ATTR_SUPPATTR | FSAL_ATTR_MODE | FSAL_ATTR_FILEID
00149       | FSAL_ATTR_TYPE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP
00150       | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME
00151       | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_SIZE
00152       | FSAL_ATTR_SPACEUSED | FSAL_ATTR_NUMLINKS | FSAL_ATTR_RAWDEV | FSAL_ATTR_FSID;
00153   fsal_attrib_mask_t unsupp;
00154 
00155   /* only those supported by filesystem */
00156   supported &= global_fs_info.supported_attrs;
00157 
00158   if(p_xattr_attrs->asked_attributes == 0)
00159     {
00160       p_xattr_attrs->asked_attributes = supported;
00161 
00162       LogCrit(COMPONENT_FSAL,
00163                         "Error: p_xattr_attrs->asked_attributes was 0 in %s() line %d, file %s",
00164                         __FUNCTION__, __LINE__, __FILE__);
00165     }
00166 
00167   unsupp = p_xattr_attrs->asked_attributes & (~supported);
00168 
00169   if(unsupp)
00170     {
00171       LogDebug(COMPONENT_FSAL,
00172                         "Asking for unsupported attributes in %s(): %#llX removing it from asked attributes",
00173                         __FUNCTION__, unsupp);
00174 
00175       p_xattr_attrs->asked_attributes &= (~unsupp);
00176     }
00177 
00178   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SUPPATTR)
00179     p_xattr_attrs->supported_attributes = supported;
00180 
00181   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE)
00182     {
00183       p_xattr_attrs->mode = file_attrs->mode & global_fs_info.xattr_access_rights;
00184 
00185       if(attr_is_read_only(attr_index))
00186         p_xattr_attrs->mode &= ~(0222);
00187     }
00188 
00189   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FILEID)
00190     {
00191       unsigned int i;
00192       unsigned long hash = attr_index + 1;
00193       char *str = (char *)&file_attrs->fileid;
00194 
00195       for(i = 0; i < sizeof(p_xattr_attrs->fileid); i++, str++)
00196         {
00197           hash = (hash << 5) - hash + (unsigned long)(*str);
00198         }
00199       p_xattr_attrs->fileid = hash;
00200     }
00201 
00202   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_TYPE)
00203     p_xattr_attrs->type = FSAL_TYPE_XATTR;
00204 
00205   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00206     p_xattr_attrs->owner = file_attrs->owner;
00207 
00208   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_GROUP)
00209     p_xattr_attrs->group = file_attrs->group;
00210 
00211   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_ATIME)
00212     p_xattr_attrs->atime = file_attrs->atime;
00213 
00214   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MTIME)
00215     p_xattr_attrs->mtime = file_attrs->mtime;
00216 
00217   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CTIME)
00218     p_xattr_attrs->ctime = file_attrs->ctime;
00219 
00220   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CREATION)
00221     p_xattr_attrs->creation = file_attrs->creation;
00222 
00223   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CHGTIME)
00224     {
00225       p_xattr_attrs->chgtime = file_attrs->chgtime;
00226       p_xattr_attrs->change = (uint64_t) p_xattr_attrs->chgtime.seconds;
00227     }
00228 
00229   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SIZE)
00230     p_xattr_attrs->filesize = DEV_BSIZE;
00231 
00232   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SPACEUSED)
00233     p_xattr_attrs->spaceused = DEV_BSIZE;
00234 
00235   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_NUMLINKS)
00236     p_xattr_attrs->numlinks = 1;
00237 
00238   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_RAWDEV)
00239     {
00240       p_xattr_attrs->rawdev.major = 0;
00241       p_xattr_attrs->rawdev.minor = 0;
00242     }
00243 
00244   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FSID)
00245     {
00246       p_xattr_attrs->fsid = file_attrs->fsid;
00247     }
00248 
00249   /* if mode==0, then owner is set to root and mode is set to 0600 */
00250   if((p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00251      && (p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE) && (p_xattr_attrs->mode == 0))
00252     {
00253       p_xattr_attrs->owner = 0;
00254       p_xattr_attrs->mode = 0600;
00255       if(attr_is_read_only(attr_index))
00256         p_xattr_attrs->mode &= ~(0200);
00257     }
00258 
00259   return 0;
00260 
00261 }
00262 
00271 fsal_status_t ZFSFSAL_GetXAttrAttrs(fsal_handle_t * p_objecthandle,        /* IN */
00272                                     fsal_op_context_t * p_context, /* IN */
00273                                     unsigned int xattr_id, /* IN */
00274                                     fsal_attrib_list_t * p_attrs
00276     )
00277 {
00278   int rc;
00279   fsal_status_t st;
00280   fsal_attrib_list_t file_attrs;
00281 
00282   /* sanity checks */
00283   if(!p_objecthandle || !p_context || !p_attrs)
00284     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrAttrs);
00285 
00286   /* object attributes we want to retrieve from parent */
00287   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00288       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE
00289       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00290 
00291   /* don't retrieve attributes not asked */
00292   file_attrs.asked_attributes &= p_attrs->asked_attributes;
00293 
00294   st = ZFSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00295 
00296   if(FSAL_IS_ERROR(st))
00297     Return(st.major, st.minor, INDEX_FSAL_GetXAttrAttrs);
00298 
00299   /* check that this index match the type of entry */
00300   if(xattr_id < XATTR_COUNT
00301      && !do_match_type(xattr_list[xattr_id].flags, file_attrs.type))
00302     {
00303       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrAttrs);
00304     }
00305   else if(xattr_id >= XATTR_COUNT)
00306     {
00307       /* This is user defined xattr */
00308       LogFullDebug(COMPONENT_FSAL,
00309                         "Getting attributes for xattr #%u", xattr_id - XATTR_COUNT);
00310     }
00311 
00312   if((rc = file_attributes_to_xattr_attrs(&file_attrs, p_attrs, xattr_id)))
00313     {
00314       Return(ERR_FSAL_INVAL, rc, INDEX_FSAL_GetXAttrAttrs);
00315     }
00316 
00317   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrAttrs);
00318 
00319 }
00320 
00333 fsal_status_t ZFSFSAL_ListXAttrs(fsal_handle_t * obj_handle,   /* IN */
00334                               unsigned int argcookie,      /* IN */
00335                               fsal_op_context_t * p_context,    /* IN */
00336                               fsal_xattrent_t * xattrs_tab,     /* IN/OUT */
00337                               unsigned int xattrs_tabsize,      /* IN */
00338                               unsigned int *p_nb_returned,      /* OUT */
00339                               int *end_of_list  /* OUT */
00340     )
00341 {
00342   unsigned int index;
00343   unsigned int out_index;
00344   fsal_status_t st;
00345   fsal_attrib_list_t file_attrs;
00346   int rc;
00347   creden_t cred;
00348   zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00349   unsigned int cookie = argcookie ;
00350 
00351   /* sanity checks */
00352   if(!p_objecthandle || !p_context || !xattrs_tab || !p_nb_returned || !end_of_list)
00353     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_ListXAttrs);
00354 
00355   /* Deal with special cookie */
00356   if( argcookie == FSAL_XATTR_RW_COOKIE ) cookie = XATTR_COUNT ;
00357 
00358   /* object attributes we want to retrieve from parent */
00359   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00360       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE
00361       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00362 
00363   /* don't retrieve unsuipported attributes */
00364   file_attrs.asked_attributes &= global_fs_info.supported_attrs;
00365 
00366   st = ZFSFSAL_getattrs(obj_handle, p_context, &file_attrs);
00367 
00368   if(FSAL_IS_ERROR(st))
00369     Return(st.major, st.minor, INDEX_FSAL_ListXAttrs);
00370 
00371   /* Get the right VFS */
00372   ZFSFSAL_VFS_RDLock();
00373   libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle);
00374   if(!p_vfs)
00375   {
00376     ZFSFSAL_VFS_Unlock();
00377     Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_ListXAttrs);
00378   }
00379 
00380 
00381   for(index = cookie, out_index = 0;
00382       index < XATTR_COUNT && out_index < xattrs_tabsize; index++)
00383     {
00384       if(do_match_type(xattr_list[index].flags, p_objecthandle->data.type))
00385         {
00386           /* fills an xattr entry */
00387           xattrs_tab[out_index].xattr_id = index;
00388           FSAL_str2name(xattr_list[index].xattr_name, FSAL_MAX_NAME_LEN,
00389                         &xattrs_tab[out_index].xattr_name);
00390           xattrs_tab[out_index].xattr_cookie = index + 1;
00391 
00392           /* set asked attributes (all supported) */
00393           xattrs_tab[out_index].attributes.asked_attributes =
00394               global_fs_info.supported_attrs;
00395 
00396           if(file_attributes_to_xattr_attrs
00397              (&file_attrs, &xattrs_tab[out_index].attributes, index))
00398             {
00399               /* set error flag */
00400               xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00401             }
00402 
00403           /* next output slot */
00404           out_index++;
00405         }
00406     }
00407 
00408   /* Save a call if the output array is full */
00409   if(out_index == xattrs_tabsize)
00410   {
00411     *end_of_list = FALSE;
00412     *p_nb_returned = out_index;
00413     ZFSFSAL_VFS_Unlock();
00414     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00415   }
00416 
00417   /* List the extended attributes */
00418   char *psz_buffer;
00419   size_t i_size;
00420 
00421   cred.uid = p_context->credential.user;
00422   cred.gid = p_context->credential.group;
00423 
00424   TakeTokenFSCall();
00425   rc = libzfswrap_listxattr(p_vfs, &cred,
00426                             p_objecthandle->data.zfs_handle, &psz_buffer, &i_size);
00427   ReleaseTokenFSCall();
00428   ZFSFSAL_VFS_Unlock();
00429 
00430   if(rc)
00431     Return(posix2fsal_error(rc), 0, INDEX_FSAL_ListXAttrs);
00432 
00433   if(i_size > 0)
00434   {
00435     size_t len = 0;
00436     char *ptr;
00437     int xattr_idx;
00438 
00439     for(ptr = psz_buffer, xattr_idx = 0;
00440         (ptr < psz_buffer + i_size) && (out_index < xattrs_tabsize);
00441         xattr_idx++, ptr += len + 1)
00442     {
00443       len = strlen(ptr);
00444       index = XATTR_COUNT + xattr_idx;
00445 
00446       /* Skip if the index is before the cookie */
00447       if(index < cookie)
00448         continue;
00449 
00450       xattrs_tab[out_index].xattr_id = index;
00451       FSAL_str2name(ptr, len + 1, &xattrs_tab[out_index].xattr_name);
00452       xattrs_tab[out_index].xattr_cookie = index + 1;
00453 
00454       /* set asked attributes (all supported) */
00455       xattrs_tab[out_index].attributes.asked_attributes =
00456                                 global_fs_info.supported_attrs;
00457 
00458       if(file_attributes_to_xattr_attrs(&file_attrs,
00459                                         &xattrs_tab[out_index].attributes,
00460                                         index))
00461       {
00462         /* set error flag */
00463         xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00464       }
00465 
00466       /* next output slot */
00467       out_index++;
00468     }
00469 
00470     /* Every xattrs are in the output array */
00471     if(ptr >= psz_buffer + i_size)
00472       *end_of_list = TRUE;
00473     else
00474       *end_of_list = FALSE;
00475   }
00476   else
00477     *end_of_list = TRUE;
00478   free(psz_buffer);
00479 
00480   *p_nb_returned = out_index;
00481 
00482   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00483 
00484 }
00485 
00486 static int xattr_id_to_name(libzfswrap_vfs_t *p_vfs, zfsfsal_op_context_t *p_context, zfsfsal_handle_t *p_objecthandle, unsigned int xattr_id, char *psz_name)
00487 {
00488   unsigned int index;
00489   unsigned int curr_idx;
00490   char *psz_buffer, *ptr;
00491   size_t i_size;
00492   size_t len;
00493   int rc;
00494   creden_t cred;
00495 
00496   if(xattr_id < XATTR_COUNT)
00497     return ERR_FSAL_INVAL;
00498 
00499   index = xattr_id - XATTR_COUNT;
00500   cred.uid = p_context->credential.user;
00501   cred.gid = p_context->credential.group;
00502 
00503   /* get xattrs */
00504 
00505   TakeTokenFSCall();
00506   rc = libzfswrap_listxattr(p_vfs, &cred,
00507                             p_objecthandle->data.zfs_handle, &psz_buffer, &i_size);
00508   ReleaseTokenFSCall();
00509 
00510   if(rc)
00511     return posix2fsal_error(rc);
00512 
00513   for(ptr = psz_buffer, curr_idx = 0; ptr < psz_buffer + i_size; curr_idx++, ptr += len + 1)
00514   {
00515       len = strlen(ptr);
00516       if(curr_idx == index)
00517       {
00518           strcpy(psz_name, ptr);
00519           free(psz_buffer);
00520           return ERR_FSAL_NO_ERROR;
00521       }
00522   }
00523   free(psz_buffer);
00524   return ERR_FSAL_NOENT;
00525 }
00526 
00531 static int xattr_name_to_id(libzfswrap_vfs_t *p_vfs, zfsfsal_op_context_t *p_context, zfsfsal_handle_t *p_objecthandle, const char *psz_name, unsigned int *p_id)
00532 {
00533   unsigned int i;
00534   char *psz_buffer, *ptr;
00535   size_t i_size;
00536   creden_t cred;
00537 
00538   cred.uid = p_context->credential.user;
00539   cred.gid = p_context->credential.group;
00540 
00541   /* get xattrs */
00542   TakeTokenFSCall();
00543   int rc = libzfswrap_listxattr(p_vfs, &cred,
00544                                 p_objecthandle->data.zfs_handle, &psz_buffer, &i_size);
00545   ReleaseTokenFSCall();
00546 
00547   if(rc)
00548     return posix2fsal_error(rc);
00549 
00550   for(ptr = psz_buffer, i = 0; ptr < psz_buffer + i_size; i++, ptr += strlen(ptr) + 1)
00551   {
00552       if(!strcmp(psz_name, ptr))
00553       {
00554         *p_id = i + XATTR_COUNT;
00555         free(psz_buffer);
00556         return ERR_FSAL_NO_ERROR;
00557       }
00558   }
00559   free(psz_buffer);
00560   return ERR_FSAL_NOENT;
00561 }
00562 
00573 fsal_status_t ZFSFSAL_GetXAttrValueById(fsal_handle_t * obj_handle,    /* IN */
00574                                      unsigned int xattr_id,     /* IN */
00575                                      fsal_op_context_t * context,     /* IN */
00576                                      caddr_t buffer_addr,       /* IN/OUT */
00577                                      size_t buffer_size,        /* IN */
00578                                      size_t * p_output_size     /* OUT */
00579     )
00580 {
00581   int rc;
00582   char buff[MAXNAMLEN];
00583   zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00584   zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context;
00585 
00586   /* sanity checks */
00587   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr)
00588     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00589 
00590   /* check that this index match the type of entry */
00591   if(xattr_id < XATTR_COUNT
00592      && !do_match_type(xattr_list[xattr_id].flags, p_objecthandle->data.type))
00593   {
00594     Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue);
00595   }
00596 
00597   /* Get the right VFS */
00598   ZFSFSAL_VFS_RDLock();
00599   libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle);
00600   if(!p_vfs)
00601   {
00602     ZFSFSAL_VFS_Unlock();
00603     Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue);
00604   }
00605 
00606   if(xattr_id >= XATTR_COUNT)
00607   {
00608     char psz_attr_name[MAXPATHLEN];
00609     char *psz_value;
00610     creden_t cred;
00611 
00612     if((rc = xattr_id_to_name(p_vfs, p_context, p_objecthandle, xattr_id, psz_attr_name)))
00613     {
00614       ZFSFSAL_VFS_Unlock();
00615       Return(rc, errno, INDEX_FSAL_GetXAttrValue);
00616     }
00617     cred.uid = p_context->credential.user;
00618     cred.gid = p_context->credential.group;
00619 
00620     if((rc = libzfswrap_getxattr(p_vfs, &cred,
00621                                  p_objecthandle->data.zfs_handle, psz_attr_name, &psz_value)))
00622     {
00623       ZFSFSAL_VFS_Unlock();
00624       Return(posix2fsal_error(rc), 0, INDEX_FSAL_GetXAttrValue);
00625     }
00626 
00627     /* Copy the string (remove this call by changing the libzfswrap API) */
00628     strncpy(buffer_addr, psz_value, buffer_size);
00629     buffer_addr[buffer_size - 1] = '\0';
00630     *p_output_size = strlen(psz_value);
00631     free(psz_value);
00632   }
00633   else
00634   {
00635     rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context,
00636                                        buffer_addr, buffer_size,
00637                                        p_output_size);
00638     /* Get the value */
00639     if(xattr_list[xattr_id].print_func == NULL)
00640       rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context,
00641                                          buffer_addr, buffer_size, p_output_size);
00642     else
00643     {
00644       rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context,
00645                                          buff, MAXNAMLEN, p_output_size);
00646       xattr_list[xattr_id].print_func(buff, MAXNAMLEN, buffer_addr, p_output_size);
00647     }
00648   }
00649 
00650   ZFSFSAL_VFS_Unlock();
00651   Return(rc, 0, INDEX_FSAL_GetXAttrValue);
00652 }
00653 
00663 fsal_status_t ZFSFSAL_GetXAttrIdByName(fsal_handle_t * obj_handle,     /* IN */
00664                                     const fsal_name_t * xattr_name,     /* IN */
00665                                     fsal_op_context_t * context,      /* IN */
00666                                     unsigned int *pxattr_id     /* OUT */
00667     )
00668 {
00669   unsigned int index;
00670   int rc;
00671   int found = FALSE;
00672   zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00673   zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context;
00674 
00675   /* sanity checks */
00676   if(!p_objecthandle || !xattr_name)
00677     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00678 
00679   for(index = 0; index < XATTR_COUNT; index++)
00680     {
00681       if(!strcmp(xattr_list[index].xattr_name, xattr_name->name))
00682         {
00683           found = TRUE;
00684           break;
00685         }
00686     }
00687 
00688   if(!found)
00689   {
00690 
00691     /* Get the right VFS */
00692     ZFSFSAL_VFS_RDLock();
00693     libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle);
00694     if(!p_vfs)
00695     {
00696       ZFSFSAL_VFS_Unlock();
00697       Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_access);
00698     }
00699 
00700     if((rc = xattr_name_to_id(p_vfs, p_context, p_objecthandle, xattr_name->name, &index)))
00701     {
00702       ZFSFSAL_VFS_Unlock();
00703       Return(rc, 0, INDEX_FSAL_GetXAttrValue);
00704     }
00705     found = TRUE;
00706   }
00707 
00708   if(found)
00709   {
00710     *pxattr_id = index;
00711     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00712   }
00713   else
00714     Return(ERR_FSAL_NOENT, ENOENT, INDEX_FSAL_GetXAttrValue);
00715 }
00716 
00727 fsal_status_t ZFSFSAL_GetXAttrValueByName(fsal_handle_t * obj_handle,  /* IN */
00728                                           const fsal_name_t * xattr_name,  /* IN */
00729                                           fsal_op_context_t * p_context,   /* IN */
00730                                           caddr_t buffer_addr,     /* IN/OUT */
00731                                           size_t buffer_size,      /* IN */
00732                                           size_t * p_output_size   /* OUT */
00733     )
00734 {
00735   unsigned int index;
00736   char *psz_value;
00737   int rc;
00738   creden_t cred;
00739   zfsfsal_handle_t *p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00740 
00741   /* sanity checks */
00742   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name)
00743     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00744 
00745   /* look for this name */
00746   for(index = 0; index < XATTR_COUNT; index++)
00747     {
00748       if(do_match_type(xattr_list[index].flags, p_objecthandle->data.type)
00749          && !strcmp(xattr_list[index].xattr_name, xattr_name->name))
00750         {
00751 
00752           return ZFSFSAL_GetXAttrValueById((fsal_handle_t *)p_objecthandle, index, p_context, buffer_addr,
00753                                            buffer_size, p_output_size);
00754         }
00755     }
00756 
00757   /* Get the right VFS */
00758   libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(p_objecthandle);
00759   if(!p_vfs)
00760   {
00761     ZFSFSAL_VFS_Unlock();
00762     Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_GetXAttrValue);
00763   }
00764   cred.uid = p_context->credential.user;
00765   cred.gid = p_context->credential.group;
00766 
00767   TakeTokenFSCall();
00768   if((rc = libzfswrap_getxattr(p_vfs, &cred,
00769                                p_objecthandle->data.zfs_handle, xattr_name->name, &psz_value)))
00770   {
00771     ZFSFSAL_VFS_Unlock();
00772     Return(posix2fsal_error(rc), 0, INDEX_FSAL_GetXAttrValue);
00773   }
00774   ZFSFSAL_VFS_Unlock();
00775 
00776   /* Copy the string (remove this call by changing the libzfswrap API) */
00777   strncpy(buffer_addr, psz_value, buffer_size);
00778   buffer_addr[buffer_size - 1] = '\0';
00779   *p_output_size = strlen(psz_value);
00780   free(psz_value);
00781 
00782   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00783 
00784 }
00785 
00786 static void chomp_attr_value(char *str, size_t size)
00787 {
00788   int len;
00789 
00790   if(str == NULL)
00791     return;
00792 
00793   /* security: set last char to '\0' */
00794   str[size - 1] = '\0';
00795 
00796   len = strnlen(str, size);
00797   if((len > 0) && (str[len - 1] == '\n'))
00798     str[len - 1] = '\0';
00799 }
00800 
00801 fsal_status_t ZFSFSAL_SetXAttrValue(fsal_handle_t * obj_handle,        /* IN */
00802                                  const fsal_name_t * xattr_name,        /* IN */
00803                                  fsal_op_context_t * p_context, /* IN */
00804                                  caddr_t buffer_addr,   /* IN */
00805                                  size_t buffer_size,    /* IN */
00806                                  int create     /* IN */
00807     )
00808 {
00809   //@TODO: use the create parameter ?
00810   int rc;
00811   creden_t cred;
00812   zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00813 
00814   /* Hook to prevent any modification in the snapshots */
00815   if(p_objecthandle->data.i_snap != 0)
00816     Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue);
00817 
00818   /* Remove trailing '\n', if any */
00819   chomp_attr_value((char*)buffer_addr, buffer_size);
00820   cred.uid = p_context->credential.user;
00821   cred.gid = p_context->credential.group;
00822 
00823   TakeTokenFSCall();
00824   rc = libzfswrap_setxattr(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred,
00825                            p_objecthandle->data.zfs_handle, xattr_name->name, (char*)buffer_addr);
00826   ReleaseTokenFSCall();
00827 
00828   if(rc)
00829     Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue);
00830 
00831   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue);
00832 }
00833 
00834 fsal_status_t ZFSFSAL_SetXAttrValueById(fsal_handle_t * obj_handle,    /* IN */
00835                                      unsigned int xattr_id,     /* IN */
00836                                      fsal_op_context_t * context,     /* IN */
00837                                      caddr_t buffer_addr,       /* IN */
00838                                      size_t buffer_size /* IN */
00839     )
00840 {
00841   int rc;
00842   char psz_name[FSAL_MAX_NAME_LEN];
00843   fsal_name_t attr_name;
00844   zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00845   zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context;
00846 
00847   /* Hook to prevent any modification in the snapshots */
00848   if(p_objecthandle->data.i_snap != 0)
00849     Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue);
00850 
00851   if(attr_is_read_only(xattr_id))
00852     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
00853   else if(xattr_id < XATTR_COUNT)
00854     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
00855 
00856   if((rc = xattr_id_to_name(p_context->export_context->p_vfs, p_context, p_objecthandle,
00857                             xattr_id, psz_name)))
00858     Return(rc, 0, INDEX_FSAL_SetXAttrValue);
00859 
00860   FSAL_str2name(psz_name, FSAL_MAX_NAME_LEN, &attr_name);
00861 
00862   return ZFSFSAL_SetXAttrValue(obj_handle, &attr_name, context,
00863                                buffer_addr, buffer_size, FALSE);
00864 }
00865 
00873 fsal_status_t ZFSFSAL_RemoveXAttrById(fsal_handle_t * obj_handle,      /* IN */
00874                                    fsal_op_context_t * context,       /* IN */
00875                                    unsigned int xattr_id)       /* IN */
00876 {
00877   int rc;
00878   creden_t cred;
00879   char psz_name[FSAL_MAX_NAME_LEN];
00880   zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00881   zfsfsal_op_context_t *p_context = (zfsfsal_op_context_t *)context;
00882 
00883   /* Hook to prevent any modification in the snapshots */
00884   if(p_objecthandle->data.i_snap != 0)
00885     Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue);
00886 
00887   if((rc = xattr_id_to_name(p_context->export_context->p_vfs, p_context, p_objecthandle,
00888                             xattr_id, psz_name)))
00889     Return(rc, 0, INDEX_FSAL_SetXAttrValue);
00890 
00891   cred.uid = p_context->credential.user;
00892   cred.gid = p_context->credential.group;
00893 
00894   TakeTokenFSCall();
00895   rc = libzfswrap_removexattr(p_context->export_context->p_vfs, &cred,
00896                               p_objecthandle->data.zfs_handle, psz_name);
00897   ReleaseTokenFSCall();
00898 
00899   if(rc)
00900     Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue);
00901   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue);
00902 }
00903 
00911 fsal_status_t ZFSFSAL_RemoveXAttrByName(fsal_handle_t * obj_handle,    /* IN */
00912                                      fsal_op_context_t * p_context,     /* IN */
00913                                      const fsal_name_t * xattr_name)    /* IN */
00914 {
00915   int rc;
00916   creden_t cred;
00917   zfsfsal_handle_t * p_objecthandle = (zfsfsal_handle_t *)obj_handle;
00918 
00919   /* Hook to prevent any modification in the snapshots */
00920   if(p_objecthandle->data.i_snap != 0)
00921     Return(ERR_FSAL_ROFS, 0, INDEX_FSAL_SetXAttrValue);
00922   cred.uid = p_context->credential.user;
00923   cred.gid = p_context->credential.group;
00924 
00925   TakeTokenFSCall();
00926   rc = libzfswrap_removexattr(((zfsfsal_op_context_t *)p_context)->export_context->p_vfs, &cred,
00927                               p_objecthandle->data.zfs_handle, xattr_name->name);
00928   ReleaseTokenFSCall();
00929 
00930   if(rc)
00931     Return(posix2fsal_error(rc), 0, INDEX_FSAL_SetXAttrValue);
00932   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue);
00933 }
00934 
00935 int ZFSFSAL_GetXattrOffsetSetable( void )
00936 {
00937   return XATTR_COUNT ;
00938 }