nfs-ganesha 1.4

fsal_xattrs.c

Go to the documentation of this file.
00001 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00011 #ifdef HAVE_CONFIG_H
00012 #include "config.h"
00013 #endif
00014 
00015 #include "fsal.h"
00016 #include "fsal_internal.h"
00017 #include "fsal_convert.h"
00018 
00019 #include <string.h>
00020 #include <time.h>
00021 #include <sys/types.h>
00022 #include <attr/xattr.h>
00023 #include "abstract_mem.h"
00024 
00025 /* generic definitions for extended attributes */
00026 
00027 #define XATTR_FOR_FILE     0x00000001
00028 #define XATTR_FOR_DIR      0x00000002
00029 #define XATTR_FOR_SYMLINK  0x00000004
00030 #define XATTR_FOR_ALL      0x0000000F
00031 #define XATTR_RO           0x00000100
00032 #define XATTR_RW           0x00000200
00033 
00034 /* function for getting an attribute value */
00035 
00036 typedef int (*xattr_getfunc_t) (xfsfsal_handle_t *,     /* object handle */
00037                                 xfsfsal_op_context_t *, /* context */
00038                                 caddr_t,        /* output buff */
00039                                 size_t, /* output buff size */
00040                                 size_t *,       /* output size */
00041                                 void *arg);     /* optionnal argument */
00042 
00043 typedef int (*xattr_setfunc_t) (xfsfsal_handle_t *,     /* object handle */
00044                                 xfsfsal_op_context_t *, /* context */
00045                                 caddr_t,        /* input buff */
00046                                 size_t, /* input size */
00047                                 int,    /* creation flag */
00048                                 void *arg);     /* optionnal argument */
00049 
00050 typedef struct fsal_xattr_def__
00051 {
00052   char xattr_name[FSAL_MAX_NAME_LEN];
00053   xattr_getfunc_t get_func;
00054   xattr_setfunc_t set_func;
00055   int flags;
00056   void *arg;
00057 } fsal_xattr_def_t;
00058 
00059 /*
00060  * DEFINE GET/SET FUNCTIONS
00061  */
00062 
00063 int print_xfshandle(xfsfsal_handle_t * p_objecthandle,  /* object handle */
00064                     xfsfsal_op_context_t * p_context,   /* IN */
00065                     caddr_t buffer_addr,        /* IN/OUT */
00066                     size_t buffer_size, /* IN */
00067                     size_t * p_output_size,     /* OUT */
00068                     void *arg)
00069 {
00070   *p_output_size =
00071       snprintmem(buffer_addr, buffer_size, p_objecthandle->data.handle_val,
00072                  p_objecthandle->data.handle_len);
00073   strncat((char *)buffer_addr, "\n", buffer_size);
00074   (*p_output_size) += 1;
00075 
00076   return 0;
00077 }                               /* print_fid */
00078 
00079 /* DEFINE HERE YOUR ATTRIBUTES LIST */
00080 
00081 static fsal_xattr_def_t xattr_list[] = {
00082   {"xfshandle", print_xfshandle, NULL, XATTR_FOR_ALL | XATTR_RO, NULL},
00083 };
00084 
00085 #define XATTR_COUNT 1
00086 
00087 /* we assume that this number is < 254 */
00088 #if ( XATTR_COUNT > 254 )
00089 #error "ERROR: xattr count > 254"
00090 #endif
00091 
00092 /* YOUR SHOULD NOT HAVE TO MODIFY THE FOLLOWING FUNCTIONS */
00093 
00094 /* test if an object has a given attribute */
00095 static int do_match_type(int xattr_flag, fsal_nodetype_t obj_type)
00096 {
00097   switch (obj_type)
00098     {
00099     case FSAL_TYPE_FILE:
00100       return ((xattr_flag & XATTR_FOR_FILE) == XATTR_FOR_FILE);
00101 
00102     case FSAL_TYPE_DIR:
00103       return ((xattr_flag & XATTR_FOR_DIR) == XATTR_FOR_DIR);
00104 
00105     case FSAL_TYPE_LNK:
00106       return ((xattr_flag & XATTR_FOR_SYMLINK) == XATTR_FOR_SYMLINK);
00107 
00108     default:
00109       return ((xattr_flag & XATTR_FOR_ALL) == XATTR_FOR_ALL);
00110     }
00111 }
00112 
00113 static int attr_is_read_only(unsigned int attr_index)
00114 {
00115   if(attr_index < XATTR_COUNT)
00116     {
00117       if(xattr_list[attr_index].flags & XATTR_RO)
00118         return TRUE;
00119     }
00120   /* else : standard xattr */
00121   return FALSE;
00122 }
00123 
00124 static int file_attributes_to_xattr_attrs(fsal_attrib_list_t * file_attrs,
00125                                           fsal_attrib_list_t * p_xattr_attrs,
00126                                           unsigned int attr_index)
00127 {
00128   /* supported attributes are:
00129    * - owner (same as the objet)
00130    * - group (same as the objet)
00131    * - type FSAL_TYPE_XATTR
00132    * - fileid (attr index ? or (fileid^((index+1)<<24)) )
00133    * - mode (config & file)
00134    * - atime, mtime, ctime = these of the object ?
00135    * - size=1block, used=1block
00136    * - rdev=0
00137    * - nlink=1
00138    */
00139   fsal_attrib_mask_t supported = FSAL_ATTR_SUPPATTR | FSAL_ATTR_MODE | FSAL_ATTR_FILEID
00140       | FSAL_ATTR_TYPE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP
00141       | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME
00142       | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_SIZE
00143       | FSAL_ATTR_SPACEUSED | FSAL_ATTR_NUMLINKS | FSAL_ATTR_RAWDEV | FSAL_ATTR_FSID;
00144   fsal_attrib_mask_t unsupp;
00145 
00146   /* only those supported by filesystem */
00147   supported &= global_fs_info.supported_attrs;
00148 
00149   if(p_xattr_attrs->asked_attributes == 0)
00150     {
00151       p_xattr_attrs->asked_attributes = supported;
00152 
00153       LogCrit(COMPONENT_FSAL,
00154                         "Error: p_xattr_attrs->asked_attributes was 0 in %s() line %d, file %s",
00155                         __FUNCTION__, __LINE__, __FILE__);
00156     }
00157 
00158   unsupp = p_xattr_attrs->asked_attributes & (~supported);
00159 
00160   if(unsupp)
00161     {
00162       LogDebug(COMPONENT_FSAL,
00163                         "Asking for unsupported attributes in %s(): %#llX removing it from asked attributes",
00164                         __FUNCTION__, unsupp);
00165 
00166       p_xattr_attrs->asked_attributes &= (~unsupp);
00167     }
00168 
00169   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SUPPATTR)
00170     p_xattr_attrs->supported_attributes = supported;
00171 
00172   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE)
00173     {
00174       p_xattr_attrs->mode = file_attrs->mode & global_fs_info.xattr_access_rights;
00175 
00176       if(attr_is_read_only(attr_index))
00177         p_xattr_attrs->mode &= ~(0222);
00178     }
00179 
00180   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FILEID)
00181     {
00182       unsigned int i;
00183       unsigned long hash = attr_index + 1;
00184       char *str = (char *)&file_attrs->fileid;
00185 
00186       for(i = 0; i < sizeof(p_xattr_attrs->fileid); i++, str++)
00187         {
00188           hash = (hash << 5) - hash + (unsigned long)(*str);
00189         }
00190       p_xattr_attrs->fileid = hash;
00191     }
00192 
00193   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_TYPE)
00194     p_xattr_attrs->type = FSAL_TYPE_XATTR;
00195 
00196   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00197     p_xattr_attrs->owner = file_attrs->owner;
00198 
00199   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_GROUP)
00200     p_xattr_attrs->group = file_attrs->group;
00201 
00202   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_ATIME)
00203     p_xattr_attrs->atime = file_attrs->atime;
00204 
00205   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MTIME)
00206     p_xattr_attrs->mtime = file_attrs->mtime;
00207 
00208   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CTIME)
00209     p_xattr_attrs->ctime = file_attrs->ctime;
00210 
00211   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CREATION)
00212     p_xattr_attrs->creation = file_attrs->creation;
00213 
00214   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CHGTIME)
00215     {
00216       p_xattr_attrs->chgtime = file_attrs->chgtime;
00217       p_xattr_attrs->change = (uint64_t) p_xattr_attrs->chgtime.seconds;
00218     }
00219 
00220   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SIZE)
00221     p_xattr_attrs->filesize = DEV_BSIZE;
00222 
00223   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SPACEUSED)
00224     p_xattr_attrs->spaceused = DEV_BSIZE;
00225 
00226   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_NUMLINKS)
00227     p_xattr_attrs->numlinks = 1;
00228 
00229   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_RAWDEV)
00230     {
00231       p_xattr_attrs->rawdev.major = 0;
00232       p_xattr_attrs->rawdev.minor = 0;
00233     }
00234 
00235   if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FSID)
00236     {
00237       p_xattr_attrs->fsid = file_attrs->fsid;
00238     }
00239 
00240   /* if mode==0, then owner is set to root and mode is set to 0600 */
00241   if((p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER)
00242      && (p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE) && (p_xattr_attrs->mode == 0))
00243     {
00244       p_xattr_attrs->owner = 0;
00245       p_xattr_attrs->mode = 0600;
00246       if(attr_is_read_only(attr_index))
00247         p_xattr_attrs->mode &= ~(0200);
00248     }
00249 
00250   return 0;
00251 
00252 }
00253 
00262 fsal_status_t XFSFSAL_GetXAttrAttrs(fsal_handle_t * p_objecthandle,  /* IN */
00263                                     fsal_op_context_t * p_context,   /* IN */
00264                                     unsigned int xattr_id,      /* IN */
00265                                     fsal_attrib_list_t * p_attrs
00267     )
00268 {
00269   int rc;
00270   fsal_status_t st;
00271   fsal_attrib_list_t file_attrs;
00272 
00273   /* sanity checks */
00274   if(!p_objecthandle || !p_context || !p_attrs)
00275     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrAttrs);
00276 
00277   /* object attributes we want to retrieve from parent */
00278   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00279       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE
00280       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00281 
00282   /* don't retrieve attributes not asked */
00283   file_attrs.asked_attributes &= p_attrs->asked_attributes;
00284 
00285   st = XFSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00286 
00287   if(FSAL_IS_ERROR(st))
00288     Return(st.major, st.minor, INDEX_FSAL_GetXAttrAttrs);
00289 
00290   /* check that this index match the type of entry */
00291   if(xattr_id < XATTR_COUNT
00292      && !do_match_type(xattr_list[xattr_id].flags, file_attrs.type))
00293     {
00294       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrAttrs);
00295     }
00296   else if(xattr_id >= XATTR_COUNT)
00297     {
00298       /* This is user defined xattr */
00299       LogFullDebug(COMPONENT_FSAL,
00300                         "Getting attributes for xattr #%u", xattr_id - XATTR_COUNT);
00301     }
00302 
00303   if((rc = file_attributes_to_xattr_attrs(&file_attrs, p_attrs, xattr_id)))
00304     {
00305       Return(ERR_FSAL_INVAL, rc, INDEX_FSAL_GetXAttrAttrs);
00306     }
00307 
00308   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrAttrs);
00309 
00310 }                               /* FSAL_GetXAttrAttrs */
00311 
00324 fsal_status_t XFSFSAL_ListXAttrs(fsal_handle_t * p_objecthandle,     /* IN */
00325                                  unsigned int argcookie,   /* IN */
00326                                  fsal_op_context_t * p_context,      /* IN */
00327                                  fsal_xattrent_t * xattrs_tab,  /* IN/OUT */
00328                                  unsigned int xattrs_tabsize,   /* IN */
00329                                  unsigned int *p_nb_returned,   /* OUT */
00330                                  int *end_of_list       /* OUT */
00331     )
00332 {
00333   unsigned int index;
00334   unsigned int out_index;
00335   fsal_status_t st;
00336   fsal_attrib_list_t file_attrs;
00337   int fd;
00338   unsigned int cookie = argcookie ;
00339 
00340   char names[MAXPATHLEN], *ptr;
00341   size_t namesize;
00342   int xattr_idx;
00343 
00344   /* sanity checks */
00345   if(!p_objecthandle || !p_context || !xattrs_tab || !p_nb_returned || !end_of_list)
00346     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_ListXAttrs);
00347 
00348   /* Deal with special cookie */
00349   if( argcookie == FSAL_XATTR_RW_COOKIE ) cookie = XATTR_COUNT ;
00350 
00351   /* object attributes we want to retrieve from parent */
00352   file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER
00353       | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE
00354       | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID;
00355 
00356   /* don't retrieve unsuipported attributes */
00357   file_attrs.asked_attributes &= global_fs_info.supported_attrs;
00358 
00359   st = XFSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00360 
00361   if(FSAL_IS_ERROR(st))
00362     Return(st.major, st.minor, INDEX_FSAL_ListXAttrs);
00363 
00364   for(index = cookie, out_index = 0;
00365       index < XATTR_COUNT && out_index < xattrs_tabsize; index++)
00366     {
00367       if(do_match_type(xattr_list[index].flags, file_attrs.type))
00368         {
00369           /* fills an xattr entry */
00370           xattrs_tab[out_index].xattr_id = index;
00371           FSAL_str2name(xattr_list[index].xattr_name, FSAL_MAX_NAME_LEN,
00372                         &xattrs_tab[out_index].xattr_name);
00373           xattrs_tab[out_index].xattr_cookie = index + 1;
00374 
00375           /* set asked attributes (all supported) */
00376           xattrs_tab[out_index].attributes.asked_attributes =
00377               global_fs_info.supported_attrs;
00378 
00379           if(file_attributes_to_xattr_attrs
00380              (&file_attrs, &xattrs_tab[out_index].attributes, index))
00381             {
00382               /* set error flag */
00383               xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00384             }
00385 
00386           /* next output slot */
00387           out_index++;
00388         }
00389     }
00390 
00391   /* save a call if output array is full */
00392   if(out_index == xattrs_tabsize)
00393     {
00394       *end_of_list = FALSE;
00395       *p_nb_returned = out_index;
00396       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00397     }
00398 
00399   /* get the path of the file in Lustre */
00400   TakeTokenFSCall();
00401   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00402   ReleaseTokenFSCall();
00403   if(FSAL_IS_ERROR(st))
00404     ReturnStatus(st, INDEX_FSAL_ListXAttrs);
00405 
00406   /* get xattrs */
00407 
00408   TakeTokenFSCall();
00409   namesize = flistxattr(fd, names, sizeof(names));
00410   ReleaseTokenFSCall();
00411 
00412   if(namesize >= 0)
00413     {
00414       size_t len = 0;
00415 
00416       errno = 0;
00417 
00418       for(ptr = names, xattr_idx = 0;
00419           (ptr < names + namesize) && (out_index < xattrs_tabsize);
00420           xattr_idx++, ptr += len + 1)
00421         {
00422           len = strlen(ptr);
00423           index = XATTR_COUNT + xattr_idx;
00424 
00425           /* skip if index is before cookie */
00426           if(index < cookie)
00427             continue;
00428 
00429           /* fills an xattr entry */
00430           xattrs_tab[out_index].xattr_id = index;
00431           FSAL_str2name(ptr, len + 1, &xattrs_tab[out_index].xattr_name);
00432           xattrs_tab[out_index].xattr_cookie = index + 1;
00433 
00434           /* set asked attributes (all supported) */
00435           xattrs_tab[out_index].attributes.asked_attributes =
00436               global_fs_info.supported_attrs;
00437 
00438           if(file_attributes_to_xattr_attrs(&file_attrs,
00439                                             &xattrs_tab[out_index].attributes, index))
00440             {
00441               /* set error flag */
00442               xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR;
00443             }
00444 
00445           /* next output slot */
00446           out_index++;
00447         }
00448       /* all xattrs are in the output array */
00449       if(ptr >= names + namesize)
00450         *end_of_list = TRUE;
00451       else
00452         *end_of_list = FALSE;
00453     }
00454   else                          /* no xattrs */
00455     *end_of_list = TRUE;
00456 
00457   *p_nb_returned = out_index;
00458 
00459   close(fd);
00460   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs);
00461 
00462 }
00463 
00464 static int xattr_id_to_name(int fd, unsigned int xattr_id, char *name)
00465 {
00466   unsigned int index;
00467   unsigned int curr_idx;
00468   char names[MAXPATHLEN], *ptr;
00469   size_t namesize;
00470   size_t len = 0;
00471 
00472   if(xattr_id < XATTR_COUNT)
00473     return ERR_FSAL_INVAL;
00474 
00475   index = xattr_id - XATTR_COUNT;
00476 
00477   /* get xattrs */
00478 
00479   TakeTokenFSCall();
00480   namesize = flistxattr(fd, names, sizeof(names));
00481   ReleaseTokenFSCall();
00482 
00483   if(namesize < 0)
00484     return ERR_FSAL_NOENT;
00485 
00486   errno = 0;
00487 
00488   for(ptr = names, curr_idx = 0; ptr < names + namesize; curr_idx++, ptr += len + 1)
00489     {
00490       len = strlen(ptr);
00491       if(curr_idx == index)
00492         {
00493           strcpy(name, ptr);
00494           return ERR_FSAL_NO_ERROR;
00495         }
00496     }
00497   return ERR_FSAL_NOENT;
00498 }
00499 
00504 static int xattr_name_to_id(int fd, const char *name)
00505 {
00506   unsigned int i;
00507   char names[MAXPATHLEN], *ptr;
00508   size_t namesize;
00509 
00510   /* get xattrs */
00511 
00512   TakeTokenFSCall();
00513   namesize = flistxattr(fd, names, sizeof(names));
00514   ReleaseTokenFSCall();
00515 
00516   if(namesize < 0)
00517     return -ERR_FSAL_NOENT;
00518 
00519   for(ptr = names, i = 0; ptr < names + namesize; i++, ptr += strlen(ptr) + 1)
00520     {
00521       if(!strcmp(name, ptr))
00522         return i + XATTR_COUNT;
00523     }
00524   return -ERR_FSAL_NOENT;
00525 }
00526 
00527 static int xattr_format_value(caddr_t buffer, size_t * datalen, size_t maxlen)
00528 {
00529   size_t size_in = *datalen;
00530   size_t len = strnlen((char *)buffer, size_in);
00531   int i;
00532 
00533   if(len == size_in - 1 || len == size_in)
00534     {
00535       int ascii = TRUE;
00536       char *str = buffer;
00537       int i;
00538 
00539       for(i = 0; i < len; i++)
00540         {
00541           if(!isprint(str[i]) && !isspace(str[i]))
00542             {
00543               ascii = FALSE;
00544               break;
00545             }
00546         }
00547 
00548       if(ascii)
00549         {
00550           *datalen = size_in;
00551           /* add additional '\n', if missing */
00552           if((size_in + 1 < maxlen) && (str[len - 1] != '\n'))
00553             {
00554               str[len] = '\n';
00555               str[len + 1] = '\0';
00556               (*datalen) += 2;
00557             }
00558           return ERR_FSAL_NO_ERROR;
00559         }
00560     }
00561 
00562   /* byte, word, 32 or 64 bits */
00563   if(size_in == 1)
00564     {
00565       unsigned char val = *((unsigned char *)buffer);
00566       *datalen = 1 + snprintf((char *)buffer, maxlen, "%hhu\n", val);
00567       return ERR_FSAL_NO_ERROR;
00568     }
00569   else if(size_in == 2)
00570     {
00571       unsigned short val = *((unsigned short *)buffer);
00572       *datalen = 1 + snprintf((char *)buffer, maxlen, "%hu\n", val);
00573       return ERR_FSAL_NO_ERROR;
00574     }
00575   else if(size_in == 4)
00576     {
00577       unsigned int val = *((unsigned int *)buffer);
00578       *datalen = 1 + snprintf((char *)buffer, maxlen, "%u\n", val);
00579       return ERR_FSAL_NO_ERROR;
00580     }
00581   else if(size_in == 8)
00582     {
00583       unsigned long long val = *((unsigned long long *)buffer);
00584       *datalen = 1 + snprintf((char *)buffer, maxlen, "%llu\n", val);
00585       return ERR_FSAL_NO_ERROR;
00586     }
00587   else
00588     {
00589       /* 2 bytes per initial byte +'0x' +\n +\0 */
00590       char *curr_out;
00591       char *tmp_buf = gsh_malloc(3 * size_in + 4);
00592       if(!tmp_buf)
00593         return ERR_FSAL_NOMEM;
00594       curr_out = tmp_buf;
00595       curr_out += sprintf(curr_out, "0x");
00596       /* hexa representation */
00597       for(i = 0; i < size_in; i++)
00598         {
00599           unsigned char *p8 = (unsigned char *)(buffer + i);
00600           if((i % 4 == 3) && (i != size_in - 1))
00601             curr_out += sprintf(curr_out, "%02hhX.", *p8);
00602           else
00603             curr_out += sprintf(curr_out, "%02hhX", *p8);
00604         }
00605       *curr_out = '\n';
00606       curr_out++;
00607       *curr_out = '\0';
00608       curr_out++;
00609       strncpy((char *)buffer, tmp_buf, maxlen);
00610       *datalen = strlen(tmp_buf) + 1;
00611       if(*datalen > maxlen)
00612         *datalen = maxlen;
00613       gsh_free(tmp_buf);
00614       return ERR_FSAL_NO_ERROR;
00615     }
00616 }
00617 
00628 fsal_status_t XFSFSAL_GetXAttrValueById(fsal_handle_t * p_objecthandle,      /* IN */
00629                                         unsigned int xattr_id,  /* IN */
00630                                         fsal_op_context_t * p_context,       /* IN */
00631                                         caddr_t buffer_addr,    /* IN/OUT */
00632                                         size_t buffer_size,     /* IN */
00633                                         size_t * p_output_size  /* OUT */
00634     )
00635 {
00636   int rc;
00637   fsal_attrib_list_t file_attrs;
00638   int fd;
00639   fsal_status_t st;
00640 
00641   /* sanity checks */
00642   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr)
00643     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00644 
00645   /* get type for checking it */
00646   file_attrs.asked_attributes = FSAL_ATTR_TYPE;
00647 
00648   st = XFSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00649 
00650   if(FSAL_IS_ERROR(st))
00651     ReturnStatus(st, INDEX_FSAL_GetXAttrValue);
00652 
00653   /* check that this index match the type of entry */
00654   if((xattr_id < XATTR_COUNT)
00655      && !do_match_type(xattr_list[xattr_id].flags, file_attrs.type))
00656     {
00657       Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue);
00658     }
00659   else if(xattr_id >= XATTR_COUNT)
00660     {
00661       char attr_name[MAXPATHLEN];
00662 
00663       TakeTokenFSCall();
00664       st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00665       ReleaseTokenFSCall();
00666       if(FSAL_IS_ERROR(st))
00667         ReturnStatus(st, INDEX_FSAL_GetXAttrValue);
00668 
00669       /* get the name for this attr */
00670       rc = xattr_id_to_name(fd, xattr_id, attr_name);
00671       if(rc)
00672         {
00673           close(fd);
00674           Return(rc, errno, INDEX_FSAL_GetXAttrValue);
00675         }
00676 
00677       rc = fgetxattr(fd, attr_name, buffer_addr, buffer_size);
00678       if(rc < 0)
00679         {
00680           close(fd);
00681           Return(posix2fsal_error(errno), errno, INDEX_FSAL_GetXAttrValue);
00682         }
00683 
00684       /* the xattr value can be a binary, or a string.
00685        * trying to determine its type...
00686        */
00687       *p_output_size = rc;
00688       xattr_format_value(buffer_addr, p_output_size, buffer_size);
00689 
00690       close(fd);
00691       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00692     }
00693   else                          /* built-in attr */
00694     {
00695       /* get the value */
00696       rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context,
00697                                          buffer_addr, buffer_size,
00698                                          p_output_size, xattr_list[xattr_id].arg);
00699       Return(rc, 0, INDEX_FSAL_GetXAttrValue);
00700     }
00701 
00702 }
00703 
00714 fsal_status_t XFSFSAL_GetXAttrIdByName(fsal_handle_t * p_objecthandle,       /* IN */
00715                                        const fsal_name_t * xattr_name,  /* IN */
00716                                        fsal_op_context_t * p_context,        /* IN */
00717                                        unsigned int *pxattr_id  /* OUT */
00718     )
00719 {
00720   fsal_status_t st;
00721   unsigned int index;
00722   int rc;
00723   int found = FALSE;
00724   int fd;
00725 
00726   /* sanity checks */
00727   if(!p_objecthandle || !xattr_name)
00728     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00729 
00730   for(index = 0; index < XATTR_COUNT; index++)
00731     {
00732       if(!strcmp(xattr_list[index].xattr_name, xattr_name->name))
00733         {
00734           found = TRUE;
00735           break;
00736         }
00737     }
00738 
00739   /* search in xattrs */
00740   if(!found)
00741     {
00742 
00743       TakeTokenFSCall();
00744       st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00745       ReleaseTokenFSCall();
00746       if(FSAL_IS_ERROR(st))
00747         ReturnStatus(st, INDEX_FSAL_GetXAttrValue);
00748 
00749       errno = 0;
00750       rc = xattr_name_to_id(fd, xattr_name->name);
00751       if(rc < 0)
00752         {
00753           close(fd);
00754           Return(-rc, errno, INDEX_FSAL_GetXAttrValue);
00755         }
00756       else
00757         {
00758           index = rc;
00759           found = TRUE;
00760         }
00761     }
00762 
00763   close(fd);
00764 
00765   if(found)
00766     {
00767       *pxattr_id = index;
00768       Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00769     }
00770   else
00771     Return(ERR_FSAL_NOENT, ENOENT, INDEX_FSAL_GetXAttrValue);
00772 }                               /* FSAL_GetXAttrIdByName */
00773 
00784 fsal_status_t XFSFSAL_GetXAttrValueByName(fsal_handle_t * p_objecthandle,    /* IN */
00785                                           const fsal_name_t * xattr_name,       /* IN */
00786                                           fsal_op_context_t * p_context,     /* IN */
00787                                           caddr_t buffer_addr,  /* IN/OUT */
00788                                           size_t buffer_size,   /* IN */
00789                                           size_t * p_output_size        /* OUT */
00790     )
00791 {
00792   unsigned int index;
00793   fsal_attrib_list_t file_attrs;
00794   fsal_status_t st;
00795   int rc;
00796   int fd;
00797 
00798   /* sanity checks */
00799   if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name)
00800     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue);
00801 
00802   /* get type for checking it */
00803   file_attrs.asked_attributes = FSAL_ATTR_TYPE;
00804 
00805   st = XFSFSAL_getattrs(p_objecthandle, p_context, &file_attrs);
00806 
00807   if(FSAL_IS_ERROR(st))
00808     ReturnStatus(st, INDEX_FSAL_GetXAttrValue);
00809 
00810   /* look for this name */
00811 
00812   for(index = 0; index < XATTR_COUNT; index++)
00813     {
00814       if(do_match_type(xattr_list[index].flags, file_attrs.type)
00815          && !strcmp(xattr_list[index].xattr_name, xattr_name->name))
00816         {
00817 
00818           return XFSFSAL_GetXAttrValueById(p_objecthandle, index, p_context, buffer_addr,
00819                                            buffer_size, p_output_size);
00820         }
00821     }
00822 
00823   TakeTokenFSCall();
00824   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00825   ReleaseTokenFSCall();
00826   if(FSAL_IS_ERROR(st))
00827     ReturnStatus(st, INDEX_FSAL_GetXAttrValue);
00828 
00829   /* is it an xattr? */
00830   rc = fgetxattr(fd, xattr_name->name, buffer_addr, buffer_size);
00831   if(rc < 0)
00832     {
00833       close(fd);
00834       Return(posix2fsal_error(errno), errno, INDEX_FSAL_GetXAttrValue);
00835     }
00836   /* the xattr value can be a binary, or a string.
00837    * trying to determine its type...
00838    */
00839   *p_output_size = rc;
00840   xattr_format_value(buffer_addr, p_output_size, buffer_size);
00841 
00842   close(fd);
00843   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue);
00844 }
00845 
00846 static void chomp_attr_value(char *str, size_t size)
00847 {
00848   int len;
00849 
00850   if(str == NULL)
00851     return;
00852 
00853   /* security: set last char to '\0' */
00854   str[size - 1] = '\0';
00855 
00856   len = strnlen(str, size);
00857   if((len > 0) && (str[len - 1] == '\n'))
00858     str[len - 1] = '\0';
00859 }
00860 
00861 fsal_status_t XFSFSAL_SetXAttrValue(fsal_handle_t * p_objecthandle,  /* IN */
00862                                     const fsal_name_t * xattr_name,     /* IN */
00863                                     fsal_op_context_t * p_context,   /* IN */
00864                                     caddr_t buffer_addr,        /* IN */
00865                                     size_t buffer_size, /* IN */
00866                                     int create  /* IN */
00867     )
00868 {
00869   int rc;
00870   fsal_status_t st;
00871   int fd = 0;
00872   size_t len;
00873 
00874   /* remove final '\n', if any */
00875   chomp_attr_value((char *)buffer_addr, buffer_size);
00876 
00877   /* build fid path in lustre */
00878   TakeTokenFSCall();
00879   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00880   ReleaseTokenFSCall();
00881   if(FSAL_IS_ERROR(st))
00882     ReturnStatus(st, INDEX_FSAL_SetXAttrValue);
00883 
00884   len = strnlen((char *)buffer_addr, buffer_size);
00885   TakeTokenFSCall();
00886   if(len == 0)
00887     rc = fsetxattr(fd, xattr_name->name, "", 1, create ? XATTR_CREATE : XATTR_REPLACE);
00888   else
00889     rc = fsetxattr(fd, xattr_name->name, (char *)buffer_addr,
00890                    len, create ? XATTR_CREATE : XATTR_REPLACE);
00891 
00892   ReleaseTokenFSCall();
00893 
00894   close(fd);
00895 
00896   if(rc != 0)
00897     Return(posix2fsal_error(errno), errno, INDEX_FSAL_SetXAttrValue);
00898   else
00899     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue);
00900 }
00901 
00902 fsal_status_t XFSFSAL_SetXAttrValueById(fsal_handle_t * p_objecthandle,      /* IN */
00903                                         unsigned int xattr_id,  /* IN */
00904                                         fsal_op_context_t * p_context,       /* IN */
00905                                         caddr_t buffer_addr,    /* IN */
00906                                         size_t buffer_size      /* IN */
00907     )
00908 {
00909   int rc;
00910   fsal_status_t st;
00911   int fd = 0;
00912   fsal_name_t attr_name;
00913   char name[FSAL_MAX_NAME_LEN];
00914 
00915   if(attr_is_read_only(xattr_id))
00916     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
00917   else if(xattr_id < XATTR_COUNT)
00918     /* this is not a UDA (setattr not supported) */
00919     Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue);
00920 
00921   /* build fid path in lustre */
00922   TakeTokenFSCall();
00923   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00924   ReleaseTokenFSCall();
00925   if(FSAL_IS_ERROR(st))
00926     ReturnStatus(st, INDEX_FSAL_SetXAttrValue);
00927 
00928   rc = xattr_id_to_name(fd, xattr_id, name);
00929   close(fd);
00930   if(rc)
00931     Return(rc, errno, INDEX_FSAL_SetXAttrValue);
00932 
00933   FSAL_str2name(name, FSAL_MAX_NAME_LEN, &attr_name);
00934 
00935   return XFSFSAL_SetXAttrValue(p_objecthandle, &attr_name,
00936                                p_context, buffer_addr, buffer_size, FALSE);
00937 }
00938 
00946 fsal_status_t XFSFSAL_RemoveXAttrById(fsal_handle_t * p_objecthandle,        /* IN */
00947                                       fsal_op_context_t * p_context, /* IN */
00948                                       unsigned int xattr_id)    /* IN */
00949 {
00950   int rc;
00951   fsal_status_t st;
00952   int fd = 0;
00953   char name[FSAL_MAX_NAME_LEN];
00954 
00955   TakeTokenFSCall();
00956   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00957   ReleaseTokenFSCall();
00958   if(FSAL_IS_ERROR(st))
00959     ReturnStatus(st, INDEX_FSAL_SetXAttrValue);
00960 
00961   rc = xattr_id_to_name(fd, xattr_id, name);
00962   if(rc)
00963     Return(rc, errno, INDEX_FSAL_SetXAttrValue);
00964 
00965   TakeTokenFSCall();
00966   rc = fremovexattr(fd, name);
00967   ReleaseTokenFSCall();
00968 
00969   close(fd);
00970 
00971   if(rc != 0)
00972     ReturnCode(posix2fsal_error(errno), errno);
00973 
00974   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00975 }                               /* FSAL_RemoveXAttrById */
00976 
00984 fsal_status_t XFSFSAL_RemoveXAttrByName(fsal_handle_t * p_objecthandle,      /* IN */
00985                                         fsal_op_context_t * p_context,       /* IN */
00986                                         const fsal_name_t * xattr_name) /* IN */
00987 {
00988   int rc;
00989   fsal_status_t st;
00990   int fd = 0;
00991 
00992   TakeTokenFSCall();
00993   st = fsal_internal_handle2fd(p_context, p_objecthandle, &fd, O_RDWR);
00994   ReleaseTokenFSCall();
00995   if(FSAL_IS_ERROR(st))
00996     ReturnStatus(st, INDEX_FSAL_SetXAttrValue);
00997 
00998   TakeTokenFSCall();
00999   rc = fremovexattr(fd, xattr_name->name);
01000   ReleaseTokenFSCall();
01001 
01002   close(fd);
01003 
01004   if(rc != 0)
01005     ReturnCode(posix2fsal_error(errno), errno);
01006 
01007   ReturnCode(ERR_FSAL_NO_ERROR, 0);
01008 }                               /* FSAL_RemoveXAttrById */
01009 
01010 int XFSFSAL_GetXattrOffsetSetable( void )
01011 {
01012   return XATTR_COUNT ;
01013 }