nfs-ganesha 1.4

fsal_attrs.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include "fsal.h"
00019 #include "fsal_internal.h"
00020 #include "fsal_convert.h"
00021 #include <sys/types.h>
00022 #include <unistd.h>
00023 #include <utime.h>
00024 
00044 fsal_status_t LUSTREFSAL_getattrs(fsal_handle_t * p_filehandle,   /* IN */
00045                                   fsal_op_context_t * p_context,  /* IN */
00046                                   fsal_attrib_list_t * p_object_attributes      /* IN/OUT */
00047     )
00048 {
00049   int rc;
00050   fsal_status_t st;
00051   fsal_path_t fsalpath;
00052   struct stat buffstat;
00053 
00054   /* sanity checks.
00055    * note : object_attributes is mandatory in FSAL_getattrs.
00056    */
00057   if(!p_filehandle || !p_context || !p_object_attributes)
00058     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);
00059 
00060   /* get the path of the file */
00061   st = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath);
00062   if(FSAL_IS_ERROR(st))
00063     ReturnStatus(st, INDEX_FSAL_getattrs);
00064 
00065   /* get file metadata */
00066   TakeTokenFSCall();
00067   rc = lstat(fsalpath.path, &buffstat);
00068   ReleaseTokenFSCall();
00069 
00070   if(rc != 0)
00071     {
00072       rc = errno;
00073       if(rc == ENOENT)
00074         Return(ERR_FSAL_STALE, rc, INDEX_FSAL_getattrs);
00075       else
00076         Return(posix2fsal_error(rc), rc, INDEX_FSAL_getattrs);
00077     }
00078 
00079   /* convert attributes */
00080   st = posix2fsal_attributes(&buffstat, p_object_attributes);
00081   if(FSAL_IS_ERROR(st))
00082     {
00083       FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00084       FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00085       ReturnStatus(st, INDEX_FSAL_getattrs);
00086     }
00087 
00088   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
00089 
00090 }
00091 
00116 fsal_status_t LUSTREFSAL_setattrs(fsal_handle_t * p_filehandle,   /* IN */
00117                                   fsal_op_context_t * p_context,  /* IN */
00118                                   fsal_attrib_list_t * p_attrib_set,    /* IN */
00119                                   fsal_attrib_list_t * p_object_attributes      /* [ IN/OUT ] */
00120     )
00121 {
00122 
00123   int rc, errsv;
00124   unsigned int i;
00125   fsal_status_t status;
00126   fsal_attrib_list_t attrs;
00127 
00128   fsal_path_t fsalpath;
00129   struct stat buffstat;
00130 
00131   /* sanity checks.
00132    * note : object_attributes is optional.
00133    */
00134   if(!p_filehandle || !p_context || !p_attrib_set)
00135     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);
00136 
00137   /* local copy of attributes */
00138   attrs = *p_attrib_set;
00139 
00140   /* First, check that FSAL attributes changes are allowed. */
00141 
00142   /* Is it allowed to change times ? */
00143 
00144   if(!global_fs_info.cansettime)
00145     {
00146 
00147       if(attrs.asked_attributes
00148          & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
00149         {
00150           /* handled as an unsettable attribute. */
00151           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
00152         }
00153     }
00154 
00155   /* apply umask, if mode attribute is to be changed */
00156   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00157     {
00158       attrs.mode &= (~global_fs_info.umask);
00159     }
00160 
00161   /* convert handle into path */
00162   status = fsal_internal_Handle2FidPath(p_context, p_filehandle, &fsalpath);
00163   if(FSAL_IS_ERROR(status))
00164     ReturnStatus(status, INDEX_FSAL_setattrs);
00165 
00166   /* get current attributes */
00167   TakeTokenFSCall();
00168   rc = lstat(fsalpath.path, &buffstat);
00169   errsv = errno;
00170   ReleaseTokenFSCall();
00171 
00172   if(rc != 0)
00173     {
00174       if(errsv == ENOENT)
00175         Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_setattrs);
00176       else
00177         Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
00178     }
00179 
00180   /***********
00181    *  CHMOD  *
00182    ***********/
00183   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00184     {
00185 
00186       /* The POSIX chmod call don't affect the symlink object, but
00187        * the entry it points to. So we must ignore it.
00188        */
00189       if(!S_ISLNK(buffstat.st_mode))
00190         {
00191 
00192           /* For modifying mode, user must be root or the owner */
00193           if((p_context->credential.user != 0)
00194              && (p_context->credential.user != buffstat.st_uid))
00195             {
00196               LogFullDebug(COMPONENT_FSAL,
00197                                 "Permission denied for CHMOD opeartion: current owner=%d, credential=%d",
00198                                 buffstat.st_uid, p_context->credential.user);
00199               Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00200             }
00201 
00202           TakeTokenFSCall();
00203           rc = chmod(fsalpath.path, fsal2unix_mode(attrs.mode));
00204           errsv = errno;
00205           ReleaseTokenFSCall();
00206 
00207           if(rc)
00208             {
00209               Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
00210             }
00211 
00212         }
00213 
00214     }
00215 
00216   /***********
00217    *  CHOWN  *
00218    ***********/
00219   /* Only root can change uid and A normal user must be in the group he wants to set */
00220   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
00221     {
00222 
00223       /* For modifying owner, user must be root or current owner==wanted==client */
00224       if((p_context->credential.user != 0) &&
00225          ((p_context->credential.user != buffstat.st_uid) ||
00226           (p_context->credential.user != attrs.owner)))
00227         {
00228           LogFullDebug(COMPONENT_FSAL,
00229                             "Permission denied for CHOWN opeartion: current owner=%d, credential=%d, new owner=%d",
00230                             buffstat.st_uid, p_context->credential.user, attrs.owner);
00231           Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00232         }
00233     }
00234 
00235   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
00236     {
00237 
00238       /* For modifying group, user must be root or current owner */
00239       if((p_context->credential.user != 0)
00240          && (p_context->credential.user != buffstat.st_uid))
00241         Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00242 
00243       int in_grp = 0;
00244       /* set in_grp */
00245       if(p_context->credential.group == attrs.group)
00246         in_grp = 1;
00247       else
00248         for(i = 0; i < p_context->credential.nbgroups; i++)
00249           {
00250             if((in_grp = (attrs.group == p_context->credential.alt_groups[i])))
00251               break;
00252           }
00253 
00254       /* it must also be in target group */
00255       if(p_context->credential.user != 0 && !in_grp)
00256         {
00257           LogFullDebug(COMPONENT_FSAL,
00258                             "Permission denied for CHOWN operation: current group=%d, credential=%d, new group=%d",
00259                             buffstat.st_gid, p_context->credential.group, attrs.group);
00260 
00261           Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00262         }
00263     }
00264 
00265   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
00266     {
00267       LogFullDebug(COMPONENT_FSAL, "Performing chown(%s, %d,%d)",
00268                         fsalpath.path, FSAL_TEST_MASK(attrs.asked_attributes,
00269                                                       FSAL_ATTR_OWNER) ? (int)attrs.owner
00270                         : -1, FSAL_TEST_MASK(attrs.asked_attributes,
00271                                              FSAL_ATTR_GROUP) ? (int)attrs.group : -1);
00272 
00273       TakeTokenFSCall();
00274       rc = lchown(fsalpath.path,
00275                   FSAL_TEST_MASK(attrs.asked_attributes,
00276                                  FSAL_ATTR_OWNER) ? (int)attrs.owner : -1,
00277                   FSAL_TEST_MASK(attrs.asked_attributes,
00278                                  FSAL_ATTR_GROUP) ? (int)attrs.group : -1);
00279       ReleaseTokenFSCall();
00280       if(rc)
00281         Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
00282     }
00283 
00284   /***********
00285    *  UTIME  *
00286    ***********/
00287 
00288   /* user must be the owner or have read access to modify 'atime' */
00289   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME)
00290      && (p_context->credential.user != 0)
00291      && (p_context->credential.user != buffstat.st_uid)
00292      && ((status = fsal_internal_testAccess(p_context, FSAL_R_OK, &buffstat, NULL)).major
00293          != ERR_FSAL_NO_ERROR))
00294     ReturnStatus(status, INDEX_FSAL_setattrs);
00295 
00296   /* user must be the owner or have write access to modify 'mtime' */
00297   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME)
00298      && (p_context->credential.user != 0)
00299      && (p_context->credential.user != buffstat.st_uid)
00300      && ((status = fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat, NULL)).major
00301          != ERR_FSAL_NO_ERROR))
00302     ReturnStatus(status, INDEX_FSAL_setattrs);
00303 
00304   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
00305     {
00306 
00307       struct utimbuf timebuf;
00308 
00309       timebuf.actime =
00310           (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t) attrs.
00311            atime.seconds : buffstat.st_atime);
00312       timebuf.modtime =
00313           (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t) attrs.
00314            mtime.seconds : buffstat.st_mtime);
00315 
00316       TakeTokenFSCall();
00317       rc = utime(fsalpath.path, &timebuf);
00318       errsv = errno;
00319       ReleaseTokenFSCall();
00320       if(rc)
00321         Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
00322 
00323     }
00324 
00325   /* Optionaly fills output attributes. */
00326 
00327   if(p_object_attributes)
00328     {
00329       status = LUSTREFSAL_getattrs(p_filehandle, p_context, p_object_attributes);
00330 
00331       /* on error, we set a special bit in the mask. */
00332       if(FSAL_IS_ERROR(status))
00333         {
00334           FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00335           FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00336         }
00337 
00338     }
00339 
00340   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
00341 
00342 }