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