nfs-ganesha 1.4

fsal_attrs.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
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 <utime.h>
00022 
00042 fsal_status_t POSIXFSAL_getattrs(fsal_handle_t * filehandle,     /* IN */
00043                                  fsal_op_context_t * context,    /* IN */
00044                                  fsal_attrib_list_t * p_object_attributes       /* IN/OUT */
00045     )
00046 {
00047   posixfsal_handle_t * p_filehandle = (posixfsal_handle_t *) filehandle;
00048   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00049   fsal_status_t status;
00050 
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   status =
00061       fsal_internal_getPathFromHandle(p_context, p_filehandle, 0, &fsalpath, &buffstat);
00062   if(FSAL_IS_ERROR(status))
00063     Return(status.major, status.minor, INDEX_FSAL_getattrs);
00064 
00065   /* convert attributes */
00066 
00067   status = posix2fsal_attributes(&buffstat, p_object_attributes);
00068   if(FSAL_IS_ERROR(status))
00069     {
00070       FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00071       FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00072       Return(status.major, status.minor, INDEX_FSAL_getattrs);
00073     }
00074 
00075   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
00076 
00077 }
00078 
00103 fsal_status_t POSIXFSAL_setattrs(fsal_handle_t * filehandle,     /* IN */
00104                                  fsal_op_context_t * context,    /* IN */
00105                                  fsal_attrib_list_t * p_attrib_set,     /* IN */
00106                                  fsal_attrib_list_t * p_object_attributes       /* [ IN/OUT ] */
00107     )
00108 {
00109   posixfsal_handle_t * p_filehandle = (posixfsal_handle_t *) filehandle;
00110   posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context;
00111   int rc, errsv;
00112   unsigned int i;
00113   fsal_status_t status;
00114   fsal_attrib_list_t attrs;
00115 
00116   fsal_path_t fsalpath;
00117   struct stat buffstat;
00118 
00119   /* sanity checks.
00120    * note : object_attributes is optional.
00121    */
00122   if(!p_filehandle || !p_context || !p_attrib_set)
00123     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);
00124 
00125   /* local copy of attributes */
00126   attrs = *p_attrib_set;
00127 
00128   /* First, check that FSAL attributes changes are allowed. */
00129 
00130   /* Is it allowed to change times ? */
00131 
00132   if(!global_fs_info.cansettime)
00133     {
00134 
00135       if(attrs.asked_attributes
00136          & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
00137         {
00138           /* handled as an unsettable attribute. */
00139           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
00140         }
00141     }
00142 
00143   /* apply umask, if mode attribute is to be changed */
00144   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00145     {
00146       attrs.mode &= (~global_fs_info.umask);
00147     }
00148 
00149   /* convert handle into path */
00150   status =
00151       fsal_internal_getPathFromHandle(p_context, p_filehandle, 0, &fsalpath, &buffstat);
00152   if(FSAL_IS_ERROR(status))
00153     Return(status.major, status.minor, INDEX_FSAL_setattrs);
00154 
00155   /***********
00156    *  CHMOD  *
00157    ***********/
00158   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00159     {
00160 
00161       /* The POSIX chmod call don't affect the symlink object, but
00162        * the entry it points to. So we must ignore it.
00163        */
00164       if(!S_ISLNK(buffstat.st_mode))
00165         {
00166 
00167           if((p_context->credential.user != 0)
00168              && (p_context->credential.user != buffstat.st_uid))
00169             Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00170 
00171           TakeTokenFSCall();
00172           rc = chmod(fsalpath.path, fsal2unix_mode(attrs.mode));
00173           errsv = errno;
00174           ReleaseTokenFSCall();
00175 
00176           if(rc)
00177             Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_setattrs);
00178 
00179         }
00180 
00181     }
00182 
00183   /***********
00184    *  CHOWN  *
00185    ***********/
00186   /* Only root can change uid and A normal user must be in the group he wants to set */
00187   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
00188     {
00189       if((p_context->credential.user != 0) &&
00190          ((p_context->credential.user != buffstat.st_uid) ||
00191           (p_context->credential.user != attrs.owner)))
00192         Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00193     }
00194 
00195   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
00196     {
00197 
00198       if(p_context->credential.user != 0 && p_context->credential.user != buffstat.st_uid)
00199         Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00200       int in_grp = 0;
00201       /* set in_grp */
00202       if(p_context->credential.group == attrs.group)
00203         in_grp = 1;
00204       else
00205         for(i = 0; i < p_context->credential.nbgroups; i++)
00206           {
00207             if((in_grp = (attrs.group == p_context->credential.alt_groups[i])))
00208               break;
00209           }
00210       if(p_context->credential.user != 0 && !in_grp)
00211         Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00212     }
00213 
00214   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
00215     {
00216       TakeTokenFSCall();
00217       rc = lchown(fsalpath.path,
00218                   FSAL_TEST_MASK(attrs.asked_attributes,
00219                                  FSAL_ATTR_OWNER) ? (int)attrs.owner : -1,
00220                   FSAL_TEST_MASK(attrs.asked_attributes,
00221                                  FSAL_ATTR_GROUP) ? (int)attrs.group : -1);
00222       ReleaseTokenFSCall();
00223       if(rc)
00224         Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
00225     }
00226 
00227   /***********
00228    *  UTIME  *
00229    ***********/
00230   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
00231     {
00232 
00233       struct utimbuf timebuf;
00234 
00235       /* user must be the owner or have read access to modify 'atime' */
00236       if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME)
00237          && (p_context->credential.user != 0)
00238          && (p_context->credential.user != buffstat.st_uid)
00239          &&
00240          ((status =
00241            fsal_internal_testAccess(p_context, FSAL_R_OK, &buffstat,
00242                                     NULL)).major != ERR_FSAL_NO_ERROR))
00243         Return(status.major, status.minor, INDEX_FSAL_setattrs);
00244 
00245       /* user must be the owner or have write access to modify 'mtime' */
00246       if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME)
00247          && (p_context->credential.user != 0)
00248          && (p_context->credential.user != buffstat.st_uid)
00249          &&
00250          ((status =
00251            fsal_internal_testAccess(p_context, FSAL_W_OK, &buffstat,
00252                                     NULL)).major != ERR_FSAL_NO_ERROR))
00253         Return(status.major, status.minor, INDEX_FSAL_setattrs);
00254 
00255       timebuf.actime =
00256           (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t) attrs.atime.
00257            seconds : buffstat.st_atime);
00258       timebuf.modtime =
00259           (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t) attrs.mtime.
00260            seconds : buffstat.st_mtime);
00261 
00262       TakeTokenFSCall();
00263       rc = utime(fsalpath.path, &timebuf);
00264       errsv = errno;
00265       ReleaseTokenFSCall();
00266       if(rc)
00267         Return(posix2fsal_error(errno), errno, INDEX_FSAL_setattrs);
00268 
00269     }
00270 
00271   /* Optionaly fills output attributes. */
00272 
00273   if(p_object_attributes)
00274     {
00275       status = POSIXFSAL_getattrs(p_filehandle, p_context, p_object_attributes);
00276 
00277       /* on error, we set a special bit in the mask. */
00278       if(FSAL_IS_ERROR(status))
00279         {
00280           FSAL_CLEAR_MASK(p_object_attributes->asked_attributes);
00281           FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00282         }
00283 
00284     }
00285 
00286   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
00287 
00288 }