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 <string.h> 00022 00043 fsal_status_t GPFSFSAL_opendir(fsal_handle_t * p_dir_handle, /* IN */ 00044 fsal_op_context_t * p_context, /* IN */ 00045 fsal_dir_t * dir_desc, /* OUT */ 00046 fsal_attrib_list_t * p_dir_attributes /* [ IN/OUT ] */ 00047 ) 00048 { 00049 fsal_status_t status; 00050 fsal_accessflags_t access_mask = 0; 00051 fsal_attrib_list_t dir_attrs; 00052 gpfsfsal_dir_t *p_dir_descriptor = (gpfsfsal_dir_t *)dir_desc; 00053 00054 /* sanity checks 00055 * note : dir_attributes is optionnal. 00056 */ 00057 if(!p_dir_handle || !p_context || !p_dir_descriptor) 00058 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); 00059 00060 /* get the path of the directory */ 00061 TakeTokenFSCall(); 00062 status = 00063 fsal_internal_handle2fd(p_context, p_dir_handle, 00064 &p_dir_descriptor->fd, 00065 O_RDONLY | O_DIRECTORY); 00066 ReleaseTokenFSCall(); 00067 00068 if(FSAL_IS_ERROR(status)) 00069 ReturnStatus(status, INDEX_FSAL_opendir); 00070 00071 /* get directory metadata */ 00072 dir_attrs.asked_attributes = GPFS_SUPPORTED_ATTRIBUTES; 00073 status = GPFSFSAL_getattrs(p_dir_handle, p_context, &dir_attrs); 00074 if(FSAL_IS_ERROR(status)) { 00075 close(p_dir_descriptor->fd); 00076 ReturnStatus(status, INDEX_FSAL_opendir); 00077 } 00078 00079 /* Test access rights for this directory */ 00080 00081 /* Set both mode and ace4 mask */ 00082 access_mask = FSAL_MODE_MASK_SET(FSAL_R_OK | FSAL_X_OK) | 00083 FSAL_ACE4_MASK_SET(FSAL_ACE_PERM_LIST_DIR); 00084 00085 if(!p_context->export_context->fe_static_fs_info->accesscheck_support) 00086 status = fsal_internal_testAccess(p_context, access_mask, NULL, &dir_attrs); 00087 else 00088 status = fsal_internal_access(p_context, p_dir_handle, access_mask, 00089 &dir_attrs); 00090 if(FSAL_IS_ERROR(status)) { 00091 close(p_dir_descriptor->fd); 00092 ReturnStatus(status, INDEX_FSAL_opendir); 00093 } 00094 00095 /* if everything is OK, fills the dir_desc structure : */ 00096 00097 memcpy(&(p_dir_descriptor->context), p_context, sizeof(fsal_op_context_t)); 00098 memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(fsal_handle_t)); 00099 00100 if(p_dir_attributes) 00101 *p_dir_attributes = dir_attrs; 00102 00103 p_dir_descriptor->dir_offset = 0; 00104 00105 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); 00106 00107 } 00108 00143 struct linux_dirent 00144 { 00145 long d_ino; 00146 long d_off; /* Be careful, SYS_getdents is a 32 bits call */ 00147 unsigned short d_reclen; 00148 char d_name[]; 00149 }; 00150 00151 #define BUF_SIZE 1024 00152 00153 fsal_status_t GPFSFSAL_readdir(fsal_dir_t * dir_desc, /* IN */ 00154 fsal_cookie_t startposition, /* IN */ 00155 fsal_attrib_mask_t get_attr_mask, /* IN */ 00156 fsal_mdsize_t buffersize, /* IN */ 00157 fsal_dirent_t * p_pdirent, /* OUT */ 00158 fsal_cookie_t * end_position, /* OUT */ 00159 fsal_count_t * p_nb_entries, /* OUT */ 00160 fsal_boolean_t * p_end_of_dir /* OUT */ 00161 ) 00162 { 00163 fsal_status_t st; 00164 fsal_count_t max_dir_entries; 00165 fsal_name_t entry_name; 00166 char buff[BUF_SIZE]; 00167 struct linux_dirent *dp = NULL; 00168 int bpos = 0; 00169 gpfsfsal_dir_t *p_dir_descriptor = (gpfsfsal_dir_t *)dir_desc; 00170 gpfsfsal_cookie_t start_position; 00171 gpfsfsal_cookie_t *p_end_position = (gpfsfsal_cookie_t *)end_position; 00172 00173 int rc = 0; 00174 00175 memset(&entry_name, 0, sizeof(fsal_name_t)); 00176 00177 /*****************/ 00178 /* sanity checks */ 00179 /*****************/ 00180 00181 if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir) 00182 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); 00183 00184 max_dir_entries = (buffersize / sizeof(fsal_dirent_t)); 00185 00186 /***************************/ 00187 /* seek into the directory */ 00188 /***************************/ 00189 start_position.data.cookie = startposition.data.cookie; 00190 errno = 0; 00191 if(start_position.data.cookie == 0) 00192 { 00193 //rewinddir(p_dir_descriptor->p_dir); 00194 rc = errno; 00195 } 00196 else 00197 { 00198 lseek(p_dir_descriptor->fd, start_position.data.cookie, SEEK_SET); 00199 rc = errno; 00200 } 00201 00202 if(rc) 00203 Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir); 00204 00205 /************************/ 00206 /* browse the directory */ 00207 /************************/ 00208 00209 *p_nb_entries = 0; 00210 while(*p_nb_entries < max_dir_entries) 00211 { 00212 /***********************/ 00213 /* read the next entry */ 00214 /***********************/ 00215 TakeTokenFSCall(); 00216 rc = syscall(SYS_getdents, p_dir_descriptor->fd, buff, BUF_SIZE); 00217 ReleaseTokenFSCall(); 00218 if(rc < 0) 00219 { 00220 rc = errno; 00221 Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir); 00222 } 00223 /* End of directory */ 00224 if(rc == 0) 00225 { 00226 *p_end_of_dir = 1; 00227 break; 00228 } 00229 00230 /***********************************/ 00231 /* Get information about the entry */ 00232 /***********************************/ 00233 00234 for(bpos = 0; bpos < rc;) 00235 { 00236 dp = (struct linux_dirent *)(buff + bpos); 00237 bpos += dp->d_reclen; 00238 00239 /* LogFullDebug(COMPONENT_FSAL, 00240 "\tino=%8ld|%8lx off=%d|%x reclen=%d|%x name=%s|%d", 00241 dp->d_ino, dp->d_ino, (int)dp->d_off, (int)dp->d_off, 00242 dp->d_reclen, dp->d_reclen, dp->d_name, (int)dp->d_name[0] ) ; */ 00243 00244 if(!(*p_nb_entries < max_dir_entries)) 00245 break; 00246 00247 /* skip . and .. */ 00248 if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 00249 continue; 00250 00251 /* build the full path of the file into "fsalpath */ 00252 if(FSAL_IS_ERROR 00253 (st = 00254 FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, 00255 &(p_pdirent[*p_nb_entries].name)))) 00256 ReturnStatus(st, INDEX_FSAL_readdir); 00257 00258 // TODO: there is a race here, because between handle fetch 00259 // and open at things might change. we need to figure out if there 00260 // is another way to open without the pcontext 00261 00262 strncpy(entry_name.name, dp->d_name, sizeof(entry_name.name)); 00263 entry_name.len = strlen(entry_name.name); 00264 00265 if(FSAL_IS_ERROR 00266 (st = 00267 fsal_internal_get_handle_at(p_dir_descriptor->fd, &entry_name, 00268 &(p_pdirent[*p_nb_entries].handle)))) 00269 ReturnStatus(st, INDEX_FSAL_readdir); 00270 00271 if(FSAL_IS_ERROR(st)) 00272 ReturnStatus(st, INDEX_FSAL_readdir); 00273 00274 /************************ 00275 * Fills the attributes * 00276 ************************/ 00277 p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask; 00278 00279 st = GPFSFSAL_getattrs(&(p_pdirent[*p_nb_entries].handle), 00280 (fsal_op_context_t *)&p_dir_descriptor->context, 00281 &p_pdirent[*p_nb_entries].attributes); 00282 if(FSAL_IS_ERROR(st)) 00283 { 00284 FSAL_CLEAR_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes); 00285 FSAL_SET_MASK(p_pdirent[*p_nb_entries].attributes.asked_attributes, 00286 FSAL_ATTR_RDATTR_ERR); 00287 } 00288 ((gpfsfsal_cookie_t *)(&p_pdirent[*p_nb_entries].cookie))->data.cookie = dp->d_off; 00289 p_pdirent[*p_nb_entries].nextentry = NULL; 00290 if(*p_nb_entries) 00291 p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]); 00292 00293 memcpy((char *)p_end_position, (char *)&p_pdirent[*p_nb_entries].cookie, 00294 sizeof(gpfsfsal_cookie_t)); 00295 (*p_nb_entries)++; 00296 00297 } /* for */ 00298 } /* While */ 00299 00300 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); 00301 00302 } 00303 00315 fsal_status_t GPFSFSAL_closedir(fsal_dir_t * p_dir_descriptor /* IN */ 00316 ) 00317 { 00318 00319 int rc; 00320 00321 /* sanity checks */ 00322 if(!p_dir_descriptor) 00323 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); 00324 00325 rc = close(((gpfsfsal_dir_t *)p_dir_descriptor)->fd); 00326 if(rc != 0) 00327 Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir); 00328 00329 /* fill dir_descriptor with zeros */ 00330 memset(p_dir_descriptor, 0, sizeof(gpfsfsal_dir_t)); 00331 00332 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); 00333 00334 }