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 #ifdef _SOLARIS
00019 #include "solaris_port.h"
00020 #endif
00021 
00022 #include "fsal.h"
00023 #include "fsal_internal.h"
00024 #include "fsal_convert.h"
00025 #include "namespace.h"
00026 
00048 fsal_status_t FUSEFSAL_getattrs(fsal_handle_t *handle, /* IN */
00049                                 fsal_op_context_t * p_context,      /* IN */
00050                                 fsal_attrib_list_t * object_attributes  /* IN/OUT */
00051     )
00052 {
00053   fusefsal_handle_t * filehandle = (fusefsal_handle_t *)handle;
00054   int rc;
00055   fsal_status_t status;
00056   struct stat obj_stat;
00057   char object_path[FSAL_MAX_PATH_LEN];
00058 
00059   /* sanity checks.
00060    * note : object_attributes is mandatory in FSAL_getattrs.
00061    */
00062   if(!filehandle || !p_context || !object_attributes)
00063     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_getattrs);
00064 
00065   /* get the full path for the object */
00066   rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator,
00067                      object_path);
00068   if(rc)
00069     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_getattrs);
00070 
00071   /* set context for the next operation, so it can be retrieved by FS thread */
00072   fsal_set_thread_context(p_context);
00073 
00074   if(p_fs_ops->getattr)
00075     {
00076       TakeTokenFSCall();
00077 
00078       rc = p_fs_ops->getattr(object_path, &obj_stat);
00079 
00080       ReleaseTokenFSCall();
00081 
00082       if(rc)
00083         Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_getattrs);
00084     }
00085   else
00086     {
00087       /* return void attributes...
00088        * Actually, should never occur since getattr
00089        * is needed for building entry's handle.
00090        */
00091 
00092       LogDebug(COMPONENT_FSAL,
00093                "FSAL_getattr WARNING: getattr is not implemented on this filesystem! Returning dummy values.");
00094 
00095       obj_stat.st_dev = filehandle->data.device;
00096       obj_stat.st_ino = filehandle->data.inode;
00097       obj_stat.st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
00098       obj_stat.st_nlink = 1;
00099       obj_stat.st_uid = 0;
00100       obj_stat.st_gid = 0;
00101       obj_stat.st_rdev = 0;
00102       obj_stat.st_size = 0;
00103       obj_stat.st_blksize = 512;
00104       obj_stat.st_blocks = 0;
00105       obj_stat.st_atime = time(NULL);
00106       obj_stat.st_mtime = time(NULL);
00107       obj_stat.st_ctime = time(NULL);
00108     }
00109 
00110   /* convert to FSAL attributes */
00111 
00112   status = posix2fsal_attributes(&obj_stat, object_attributes);
00113 
00114   if(FSAL_IS_ERROR(status))
00115     {
00116       FSAL_CLEAR_MASK(object_attributes->asked_attributes);
00117       FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00118       Return(status.major, status.minor, INDEX_FSAL_getattrs);
00119     }
00120 
00121   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_getattrs);
00122 
00123 }
00124 
00158 fsal_status_t FUSEFSAL_setattrs(fsal_handle_t *handle, /* IN */
00159                                 fsal_op_context_t * p_context,      /* IN */
00160                                 fsal_attrib_list_t * attrib_set,        /* IN */
00161                                 fsal_attrib_list_t * object_attributes  /* [ IN/OUT ] */
00162     )
00163 {
00164   fusefsal_handle_t * filehandle = (fusefsal_handle_t *)handle;
00165   int rc;
00166   fsal_status_t status;
00167   fsal_attrib_list_t attrs;
00168   fsal_attrib_list_t tmp_attrs;
00169   char object_path[FSAL_MAX_PATH_LEN];
00170 
00171   /* sanity checks.
00172    * note : object_attributes is optional.
00173    */
00174   if(!filehandle || !p_context || !attrib_set)
00175     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_setattrs);
00176 
00177   /* local copy of attributes */
00178   attrs = *attrib_set;
00179 
00180   /* First, check that FSAL attributes changes are allowed. */
00181 
00182   /* Is it allowed to change times ? */
00183 
00184   if(!global_fs_info.cansettime)
00185     {
00186 
00187       if(attrs.asked_attributes
00188          & (FSAL_ATTR_ATIME | FSAL_ATTR_CREATION | FSAL_ATTR_CTIME | FSAL_ATTR_MTIME))
00189         {
00190 
00191           /* handled as an unsettable attribute. */
00192           Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_setattrs);
00193         }
00194 
00195     }
00196 
00197   /* apply umask, if mode attribute is to be changed */
00198 
00199   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00200     {
00201       attrs.mode &= (~global_fs_info.umask);
00202     }
00203 
00204   /* get the path for this entry */
00205 
00206   rc = NamespacePath(filehandle->data.inode, filehandle->data.device, filehandle->data.validator,
00207                      object_path);
00208   if(rc)
00209     Return(ERR_FSAL_STALE, rc, INDEX_FSAL_setattrs);
00210 
00211   /* set context for the next operation, so it can be retrieved by FS thread */
00212   fsal_set_thread_context(p_context);
00213 
00214   /**********
00215    *  CHMOD *
00216    **********/
00217   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MODE))
00218     {
00219       /* /!\ this must be ignored for symlinks */
00220       /* We must retrieve initial value of atime and mtime because
00221        * utimens changes both of them    */
00222       fsal_status_t status;
00223 
00224       FSAL_CLEAR_MASK(tmp_attrs.asked_attributes);
00225       FSAL_SET_MASK(tmp_attrs.asked_attributes, FSAL_ATTR_TYPE);
00226 
00227       status = FUSEFSAL_getattrs(filehandle, p_context, &tmp_attrs);
00228 
00229       if(FSAL_IS_ERROR(status))
00230         Return(status.major, status.minor, INDEX_FSAL_setattrs);
00231 
00232       if((tmp_attrs.type != FSAL_TYPE_LNK) && (p_fs_ops->chmod != NULL))
00233         {
00234           TakeTokenFSCall();
00235           rc = p_fs_ops->chmod(object_path, fsal2unix_mode(attrs.mode));
00236           ReleaseTokenFSCall();
00237 
00238           LogFullDebug(COMPONENT_FSAL, "chmod: status = %d", rc);
00239 
00240           if(rc)
00241             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_setattrs);
00242         }
00243       /* else : ignored */
00244 
00245     }
00246 
00247   /*************
00248    *  TRUNCATE *
00249    *************/
00250   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_SIZE))
00251     {
00252 
00253       if(p_fs_ops->truncate)
00254         {
00255           TakeTokenFSCall();
00256           rc = p_fs_ops->truncate(object_path, (off_t) attrs.filesize);
00257           ReleaseTokenFSCall();
00258 
00259           LogFullDebug(COMPONENT_FSAL, "truncate: status = %d", rc);
00260 
00261           if(rc)
00262             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_setattrs);
00263         }
00264       /* else : ignored */
00265 
00266     }
00267 
00268   /***********
00269    *  CHOWN  *
00270    ***********/
00271   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER))
00272     {
00273       if((p_context->credential.user != 0) && (p_context->credential.user != attrs.owner))
00274         {
00275           LogEvent(COMPONENT_FSAL,
00276                    "FSAL_setattr: Denied user %d to change object's owner to %d",
00277                    p_context->credential.user, attrs.owner);
00278           Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00279         }
00280     }
00281 
00282   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_GROUP))
00283     {
00284       if((p_context->credential.user != 0)
00285          && (p_context->credential.group != attrs.group))
00286         {
00287           LogEvent(COMPONENT_FSAL,
00288                    "FSAL_setattr: Denied user %d (group %d) to change object's group to %d",
00289                    p_context->credential.user, p_context->credential.group,
00290                    attrs.group);
00291           Return(ERR_FSAL_PERM, 0, INDEX_FSAL_setattrs);
00292         }
00293     }
00294 
00295   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_OWNER | FSAL_ATTR_GROUP))
00296     {
00297       if(p_fs_ops->chown)
00298         {
00299           TakeTokenFSCall();
00300           rc = p_fs_ops->chown(object_path,
00301                                FSAL_TEST_MASK(attrs.asked_attributes,
00302                                               FSAL_ATTR_OWNER) ? (uid_t) attrs.owner : -1,
00303                                FSAL_TEST_MASK(attrs.asked_attributes,
00304                                               FSAL_ATTR_GROUP) ? (gid_t) attrs.group :
00305                                -1);
00306           ReleaseTokenFSCall();
00307 
00308           LogFullDebug(COMPONENT_FSAL, "chown: status = %d", rc);
00309 
00310           if(rc)
00311             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_setattrs);
00312         }
00313       /* else : ignored */
00314     }
00315 
00316   /***********
00317    *  UTIME  *
00318    ***********/
00319   if(FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME | FSAL_ATTR_MTIME))
00320     {
00321 
00322       /* We must retrieve initial value of atime and mtime because
00323        * utimens changes both of them    */
00324       fsal_status_t status;
00325 
00326       FSAL_CLEAR_MASK(tmp_attrs.asked_attributes);
00327       FSAL_SET_MASK(tmp_attrs.asked_attributes, FSAL_ATTR_ATIME);
00328       FSAL_SET_MASK(tmp_attrs.asked_attributes, FSAL_ATTR_MTIME);
00329 
00330       status = FUSEFSAL_getattrs(filehandle, p_context, &tmp_attrs);
00331 
00332       if(FSAL_IS_ERROR(status))
00333         Return(status.major, status.minor, INDEX_FSAL_setattrs);
00334 
00335       /* utimens is provided */
00336 
00337       if(p_fs_ops->utimens)
00338         {
00339           struct timespec tv[2];
00340 
00341           tv[0].tv_sec =
00342               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t)
00343                attrs.atime.seconds : tmp_attrs.atime.seconds);
00344           tv[0].tv_nsec =
00345               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t)
00346                attrs.atime.nseconds : tmp_attrs.atime.nseconds);
00347 
00348           tv[1].tv_sec =
00349               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t)
00350                attrs.mtime.seconds : tmp_attrs.mtime.seconds);
00351           tv[1].tv_nsec =
00352               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t)
00353                attrs.mtime.nseconds : tmp_attrs.mtime.nseconds);
00354 
00355           TakeTokenFSCall();
00356           rc = p_fs_ops->utimens(object_path, tv);
00357           ReleaseTokenFSCall();
00358 
00359           LogFullDebug(COMPONENT_FSAL, "utimens: status = %d", rc);
00360 
00361           if(rc)
00362             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_setattrs);
00363         }
00364       else if(p_fs_ops->utime)
00365         {
00366           /* utime is provided */
00367           struct utimbuf utb;
00368 
00369           utb.actime =
00370               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_ATIME) ? (time_t)
00371                attrs.atime.seconds : tmp_attrs.atime.seconds);
00372           utb.modtime =
00373               (FSAL_TEST_MASK(attrs.asked_attributes, FSAL_ATTR_MTIME) ? (time_t)
00374                attrs.mtime.seconds : tmp_attrs.mtime.seconds);
00375 
00376           TakeTokenFSCall();
00377           rc = p_fs_ops->utime(object_path, &utb);
00378           ReleaseTokenFSCall();
00379 
00380           LogFullDebug(COMPONENT_FSAL, "utime: status = %d", rc);
00381 
00382           if(rc)
00383             Return(fuse2fsal_error(rc, TRUE), rc, INDEX_FSAL_setattrs);
00384         }
00385       /* else : ignored */
00386 
00387     }
00388 
00389   /* atime/mtime */
00390   /* Optionaly fill output attributes. */
00391   if(object_attributes)
00392     {
00393 
00394       status = FUSEFSAL_getattrs(filehandle, p_context, object_attributes);
00395 
00396       /* on error, we set a special bit in the mask. */
00397       if(FSAL_IS_ERROR(status))
00398         {
00399           FSAL_CLEAR_MASK(object_attributes->asked_attributes);
00400           FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00401         }
00402 
00403     }
00404 
00405   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_setattrs);
00406 
00407 }                               /* FSAL_setattrs */