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