nfs-ganesha 1.4
|
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 }