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 "abstract_mem.h" 00022 #include <string.h> 00023 00044 fsal_status_t POSIXFSAL_opendir(fsal_handle_t * dir_handle, /* IN */ 00045 fsal_op_context_t * context, /* IN */ 00046 fsal_dir_t * dir_descriptor, /* OUT */ 00047 fsal_attrib_list_t * p_dir_attributes /* [ IN/OUT ] */ 00048 ) 00049 { 00050 posixfsal_handle_t * p_dir_handle = (posixfsal_handle_t *) dir_handle; 00051 posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; 00052 posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; 00053 int rc; 00054 fsal_status_t status; 00055 00056 fsal_path_t fsalpath; 00057 struct stat buffstat; 00058 00059 /* sanity checks 00060 * note : dir_attributes is optionnal. 00061 */ 00062 if(!p_dir_handle || !p_context || !p_dir_descriptor) 00063 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); 00064 00065 /* get the path of the directory */ 00066 status = 00067 fsal_internal_getPathFromHandle(p_context, p_dir_handle, 1, &fsalpath, &buffstat); 00068 if(FSAL_IS_ERROR(status)) 00069 Return(status.major, status.minor, INDEX_FSAL_opendir); 00070 00071 /* Test access rights for this directory */ 00072 00073 status = fsal_internal_testAccess(p_context, FSAL_R_OK, &buffstat, NULL); 00074 if(FSAL_IS_ERROR(status)) 00075 Return(status.major, status.minor, INDEX_FSAL_opendir); 00076 00077 /* if everything is OK, fills the dir_desc structure : */ 00078 00079 TakeTokenFSCall(); 00080 p_dir_descriptor->p_dir = opendir(fsalpath.path); 00081 ReleaseTokenFSCall(); 00082 if(!p_dir_descriptor->p_dir) 00083 Return(posix2fsal_error(errno), errno, INDEX_FSAL_opendir); 00084 00085 memcpy(&(p_dir_descriptor->context), p_context, sizeof(posixfsal_op_context_t)); 00086 memcpy(&(p_dir_descriptor->path), &fsalpath, sizeof(fsal_path_t)); 00087 memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(posixfsal_handle_t)); 00088 00089 #ifdef _USE_POSIXDB_READDIR_BLOCK 00090 p_dir_descriptor->p_dbentries = NULL; 00091 p_dir_descriptor->dbentries_count = 0; 00092 /* fill the p_dbentries list */ 00093 statusdb = fsal_posixdb_getChildren(p_dir_descriptor->context.p_conn, 00094 &(p_dir_descriptor->handle), 00095 FSAL_POSIXDB_MAXREADDIRBLOCKSIZE, 00096 &(p_dir_descriptor->p_dbentries), 00097 &(p_dir_descriptor->dbentries_count)); 00098 if(FSAL_POSIXDB_IS_ERROR(statusdb)) /* too many entries in the directory, or another error */ 00099 p_dir_descriptor->dbentries_count = -1; 00100 00101 #endif 00102 if(p_dir_attributes) 00103 { 00104 00105 TakeTokenFSCall(); 00106 rc = lstat(fsalpath.path, &buffstat); 00107 ReleaseTokenFSCall(); 00108 if(rc) /* lstat failed */ 00109 goto attr_err; 00110 00111 status = posix2fsal_attributes(&buffstat, p_dir_attributes); 00112 if(FSAL_IS_ERROR(status)) 00113 { 00114 attr_err: 00115 FSAL_CLEAR_MASK(p_dir_attributes->asked_attributes); 00116 FSAL_SET_MASK(p_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00117 } 00118 } 00119 00120 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); 00121 00122 } 00123 00157 fsal_status_t POSIXFSAL_readdir(fsal_dir_t * dir_descriptor, /* IN */ 00158 fsal_cookie_t start_pos, /* IN */ 00159 fsal_attrib_mask_t get_attr_mask, /* IN */ 00160 fsal_mdsize_t buffersize, /* IN */ 00161 fsal_dirent_t * p_pdirent, /* OUT */ 00162 fsal_cookie_t * end_position, /* OUT */ 00163 fsal_count_t * p_nb_entries, /* OUT */ 00164 fsal_boolean_t * p_end_of_dir /* OUT */ 00165 ) 00166 { 00167 posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; 00168 posixfsal_cookie_t start_position, telldir_pos; 00169 posixfsal_cookie_t * p_end_position = (posixfsal_cookie_t *) end_position; 00170 fsal_status_t st; 00171 fsal_posixdb_status_t stdb; 00172 fsal_count_t max_dir_entries; 00173 struct dirent *dp; 00174 struct dirent dpe; 00175 struct stat buffstat; 00176 fsal_path_t fsalpath; 00177 fsal_posixdb_fileinfo_t infofs; 00178 int rc; 00179 00180 /*****************/ 00181 /* sanity checks */ 00182 /*****************/ 00183 00184 if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir) 00185 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); 00186 00187 max_dir_entries = (buffersize / sizeof(fsal_dirent_t)); 00188 00189 /***************************/ 00190 /* seek into the directory */ 00191 /***************************/ 00192 memcpy ( (char *)&start_position.data.cookie, (char *)&start_pos.data, sizeof( off_t ) ) ; 00193 00194 errno = 0; 00195 if(start_position.data.cookie == 0) 00196 { 00197 rewinddir(p_dir_descriptor->p_dir); 00198 rc = errno; 00199 } 00200 else 00201 { 00202 seekdir(p_dir_descriptor->p_dir, start_position.data.cookie); 00203 rc = errno; 00204 } 00205 00206 if(rc) 00207 { 00208 st.major = posix2fsal_error(rc); 00209 st.minor = rc; 00210 goto readdir_error; 00211 } 00212 00213 /************************/ 00214 /* browse the directory */ 00215 /************************/ 00216 00217 *p_nb_entries = 0; 00218 while(*p_nb_entries < max_dir_entries) 00219 { 00220 /***********************/ 00221 /* read the next entry */ 00222 /***********************/ 00223 TakeTokenFSCall(); 00224 rc = readdir_r(p_dir_descriptor->p_dir, &dpe, &dp); 00225 ReleaseTokenFSCall(); 00226 if(rc) 00227 { 00228 st.major = posix2fsal_error(errno); 00229 st.minor = errno; 00230 goto readdir_error; 00231 } /* End of directory */ 00232 if(!dp) 00233 { 00234 *p_end_of_dir = 1; 00235 break; 00236 } 00237 00238 /***********************************/ 00239 /* Get information about the entry */ 00240 /***********************************/ 00241 00242 /* build the full path of the file into "fsalpath */ 00243 if(FSAL_IS_ERROR 00244 (st = 00245 FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, &(p_pdirent[*p_nb_entries].name)))) 00246 goto readdir_error; 00247 memcpy(&fsalpath, &(p_dir_descriptor->path), sizeof(fsal_path_t)); 00248 st = fsal_internal_appendFSALNameToFSALPath(&fsalpath, 00249 &(p_pdirent[*p_nb_entries].name)); 00250 if(FSAL_IS_ERROR(st)) 00251 goto readdir_error; 00252 00253 /* get object info */ 00254 TakeTokenFSCall(); 00255 rc = lstat(fsalpath.path, &buffstat); 00256 ReleaseTokenFSCall(); 00257 if(rc) 00258 { 00259 st.major = posix2fsal_error(errno); 00260 st.minor = errno; 00261 goto readdir_error; 00262 } 00263 if(FSAL_IS_ERROR(st = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs))) 00264 goto readdir_error; 00265 00266 /********************/ 00267 /* fills the handle */ 00268 /********************/ 00269 00270 /* check for "." and ".." */ 00271 if(!strcmp(dp->d_name, ".")) 00272 { 00273 memcpy(&(p_pdirent[*p_nb_entries].handle), &(p_dir_descriptor->handle), 00274 sizeof(posixfsal_handle_t)); 00275 } 00276 else if(!strcmp(dp->d_name, "..")) 00277 { 00278 stdb = fsal_posixdb_getParentDirHandle(p_dir_descriptor->context.p_conn, 00279 &(p_dir_descriptor->handle), 00280 (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle)); 00281 if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) 00282 goto readdir_error; 00283 } 00284 else 00285 { 00286 #ifdef _USE_POSIXDB_READDIR_BLOCK 00287 if(p_dir_descriptor->dbentries_count > -1) 00288 { /* look for the entry in dbentries */ 00289 st = fsal_internal_getInfoFromChildrenList(&(p_dir_descriptor->context), 00290 &(p_dir_descriptor->handle), 00291 &(p_pdirent[*p_nb_entries].name), 00292 &infofs, 00293 p_dir_descriptor->p_dbentries, 00294 p_dir_descriptor-> 00295 dbentries_count, 00296 &(p_pdirent[*p_nb_entries]. 00297 handle)); 00298 } 00299 else 00300 #endif 00301 { /* get handle for the entry */ 00302 st = fsal_internal_getInfoFromName(&(p_dir_descriptor->context), 00303 &(p_dir_descriptor->handle), 00304 &(p_pdirent[*p_nb_entries].name), 00305 &infofs, 00306 (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle)); 00307 } 00308 if(FSAL_IS_ERROR(st)) 00309 goto readdir_error; 00310 } /* end of name check for "." and ".." */ 00311 00312 /************************ 00313 * Fills the attributes * 00314 ************************/ 00315 p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask; 00316 st = posix2fsal_attributes(&buffstat, &(p_pdirent[*p_nb_entries].attributes)); 00317 if(FSAL_IS_ERROR(st)) 00318 goto readdir_error; 00319 00320 /* 00321 * 00322 **/ 00323 telldir_pos.data.cookie = telldir(p_dir_descriptor->p_dir); 00324 memcpy(&p_pdirent[*p_nb_entries].cookie, &telldir_pos, sizeof(fsal_cookie_t)); 00325 p_pdirent[*p_nb_entries].nextentry = NULL; 00326 if(*p_nb_entries) 00327 p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]); 00328 00329 memcpy(p_end_position, &p_pdirent[*p_nb_entries].cookie, sizeof(fsal_cookie_t)); 00330 (*p_nb_entries)++; 00331 }; 00332 00333 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); 00334 00335 /* return error, and free what must be freed */ 00336 readdir_error: 00337 Return(st.major, st.minor, INDEX_FSAL_readdir); 00338 } 00339 00351 fsal_status_t POSIXFSAL_closedir(fsal_dir_t * dir_descriptor /* IN */ ) 00352 { 00353 posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; 00354 int rc; 00355 00356 /* sanity checks */ 00357 if(!p_dir_descriptor) 00358 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); 00359 00360 #ifdef _USE_POSIXDB_READDIR_BLOCK 00361 if(p_dir_descriptor->p_dbentries) 00362 gsh_free(p_dir_descriptor->p_dbentries); 00363 #endif 00364 00365 rc = closedir(p_dir_descriptor->p_dir); 00366 if(rc != 0) 00367 Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir); 00368 00369 /* fill dir_descriptor with zeros */ 00370 memset(p_dir_descriptor, 0, sizeof(posixfsal_dir_t)); 00371 00372 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); 00373 00374 }