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/access_check.h" 00021 #include "fsal_convert.h" 00022 #include <string.h> 00023 00044 fsal_status_t XFSFSAL_opendir(fsal_handle_t * p_dir_handle, /* IN */ 00045 fsal_op_context_t * p_context, /* IN */ 00046 fsal_dir_t *dir_desc, /* OUT */ 00047 fsal_attrib_list_t * p_dir_attributes /* [ IN/OUT ] */ 00048 ) 00049 { 00050 xfsfsal_dir_t * p_dir_descriptor = (xfsfsal_dir_t *) dir_desc; 00051 int rc = 0 , errsv = 0 ; 00052 fsal_status_t status; 00053 00054 struct stat buffstat; 00055 00056 /* sanity checks 00057 * note : dir_attributes is optionnal. 00058 */ 00059 if(!p_dir_handle || !p_context || !p_dir_descriptor) 00060 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); 00061 00062 /* get the path of the directory */ 00063 TakeTokenFSCall(); 00064 status = 00065 fsal_internal_handle2fd(p_context, p_dir_handle, &p_dir_descriptor->fd, 00066 O_RDONLY | O_DIRECTORY); 00067 ReleaseTokenFSCall(); 00068 00069 if(FSAL_IS_ERROR(status)) 00070 ReturnStatus(status, INDEX_FSAL_opendir); 00071 00072 /* get directory metadata */ 00073 TakeTokenFSCall(); 00074 rc = fstat(p_dir_descriptor->fd, &buffstat); 00075 ReleaseTokenFSCall(); 00076 00077 if(rc != 0) 00078 { 00079 close(p_dir_descriptor->fd); 00080 if(rc == ENOENT) 00081 Return(ERR_FSAL_STALE, errsv, INDEX_FSAL_opendir); 00082 else 00083 Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_opendir); 00084 } 00085 00086 /* Test access rights for this directory */ 00087 status = fsal_check_access(p_context, FSAL_R_OK, &buffstat, NULL); 00088 if(FSAL_IS_ERROR(status)) 00089 ReturnStatus(status, INDEX_FSAL_opendir); 00090 00091 /* if everything is OK, fills the dir_desc structure : */ 00092 00093 memcpy(&(p_dir_descriptor->context), p_context, sizeof(xfsfsal_op_context_t)); 00094 memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(xfsfsal_handle_t)); 00095 00096 if(p_dir_attributes) 00097 { 00098 status = posix2fsal_attributes(&buffstat, p_dir_attributes); 00099 if(FSAL_IS_ERROR(status)) 00100 { 00101 FSAL_CLEAR_MASK(p_dir_attributes->asked_attributes); 00102 FSAL_SET_MASK(p_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00103 } 00104 } 00105 00106 p_dir_descriptor->dir_offset = 0; 00107 00108 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); 00109 00110 } 00111 00112 /* 00113 * Common code used by fsal_lookup and fsal_readdir - 00114 * given the name try to stat an entry. If an entry is 00115 * regular file or directory then open it and use fd2handle 00116 * to get a real handle, otherwise use inum2handle to fake 00117 * a handle. 00118 */ 00119 fsal_status_t 00120 xfsfsal_stat_by_name(fsal_op_context_t * context, 00121 int atfd, 00122 const char *name, 00123 fsal_handle_t *handle, 00124 fsal_attrib_list_t * attributes) 00125 { 00126 int rc; 00127 int errsv; 00128 struct stat buffstat; 00129 fsal_status_t st; 00130 00131 TakeTokenFSCall(); 00132 rc = fstatat(atfd, name, &buffstat, AT_SYMLINK_NOFOLLOW); 00133 errsv = errno; 00134 ReleaseTokenFSCall(); 00135 if(rc < 0) 00136 ReturnCode(posix2fsal_error(errsv), errsv); 00137 00138 if(S_ISDIR(buffstat.st_mode) || S_ISREG(buffstat.st_mode)) 00139 { 00140 int tmpfd; 00141 00142 TakeTokenFSCall(); 00143 tmpfd = openat(atfd, name, O_RDONLY | O_NOFOLLOW, 0600); 00144 errsv = errno; 00145 ReleaseTokenFSCall(); 00146 if(tmpfd < 0) 00147 ReturnCode(posix2fsal_error(errsv), errsv); 00148 00149 st = fsal_internal_fd2handle(context, tmpfd, handle); 00150 close(tmpfd); 00151 } 00152 else 00153 { 00154 st = fsal_internal_inum2handle(context, buffstat.st_ino, handle); 00155 } 00156 00157 if(FSAL_IS_ERROR(st)) 00158 return st; 00159 00160 if(attributes) 00161 { 00162 st = posix2fsal_attributes(&buffstat, attributes); 00163 if(FSAL_IS_ERROR(st)) 00164 { 00165 FSAL_CLEAR_MASK(attributes->asked_attributes); 00166 FSAL_SET_MASK(attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00167 } 00168 } 00169 return st; 00170 } 00171 00172 00207 struct linux_dirent 00208 { 00209 long d_ino; 00210 long d_off; /* Be careful, SYS_getdents is a 32 bits call */ 00211 unsigned short d_reclen; 00212 char d_name[]; 00213 }; 00214 00215 #define BUF_SIZE 1024 00216 00217 fsal_status_t XFSFSAL_readdir(fsal_dir_t * dir_descriptor, /* IN */ 00218 fsal_cookie_t startposition, /* IN */ 00219 fsal_attrib_mask_t get_attr_mask, /* IN */ 00220 fsal_mdsize_t buffersize, /* IN */ 00221 fsal_dirent_t * p_pdirent, /* OUT */ 00222 fsal_cookie_t * end_position, /* OUT */ 00223 fsal_count_t * p_nb_entries, /* OUT */ 00224 fsal_boolean_t * p_end_of_dir /* OUT */ 00225 ) 00226 { 00227 xfsfsal_dir_t * p_dir_descriptor = (xfsfsal_dir_t * ) dir_descriptor; 00228 xfsfsal_cookie_t start_position; 00229 xfsfsal_cookie_t * p_end_position = (xfsfsal_cookie_t *) end_position; 00230 fsal_status_t st; 00231 fsal_count_t max_dir_entries; 00232 char buff[BUF_SIZE]; 00233 struct linux_dirent *dp = NULL; 00234 int bpos = 0; 00235 00236 int rc = 0; 00237 00238 memset(buff, 0, BUF_SIZE); 00239 00240 /*****************/ 00241 /* sanity checks */ 00242 /*****************/ 00243 00244 if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir) 00245 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); 00246 00247 max_dir_entries = (buffersize / sizeof(fsal_dirent_t)); 00248 00249 /***************************/ 00250 /* seek into the directory */ 00251 /***************************/ 00252 memcpy( (char *)&start_position.data.cookie, (char *)&startposition.data, sizeof( off_t ) ) ; 00253 rc = errno = 0; 00254 lseek(p_dir_descriptor->fd, start_position.data.cookie, SEEK_SET); 00255 rc = errno; 00256 00257 if(rc) 00258 Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir); 00259 00260 /************************/ 00261 /* browse the directory */ 00262 /************************/ 00263 00264 *p_nb_entries = 0; 00265 while(*p_nb_entries < max_dir_entries) 00266 { 00267 /***********************/ 00268 /* read the next entry */ 00269 /***********************/ 00270 TakeTokenFSCall(); 00271 rc = syscall(SYS_getdents, p_dir_descriptor->fd, buff, BUF_SIZE); 00272 ReleaseTokenFSCall(); 00273 if(rc < 0) 00274 { 00275 rc = errno; 00276 Return(posix2fsal_error(rc), rc, INDEX_FSAL_readdir); 00277 } 00278 /* End of directory */ 00279 if(rc == 0) 00280 { 00281 *p_end_of_dir = 1; 00282 break; 00283 } 00284 00285 /***********************************/ 00286 /* Get information about the entry */ 00287 /***********************************/ 00288 00289 for(bpos = 0; bpos < rc;) 00290 { 00291 dp = (struct linux_dirent *)(buff + bpos); 00292 bpos += dp->d_reclen; 00293 00294 /* LogFullDebug(COMPONENT_FSAL, "\tino=%8ld|%8lx off=%d|%x reclen=%d|%x name=%s|%d", dp->d_ino, dp->d_ino, (int)dp->d_off, (int)dp->d_off, 00295 dp->d_reclen, dp->d_reclen, dp->d_name, (int)dp->d_name[0] ) ; */ 00296 00297 if(!(*p_nb_entries < max_dir_entries)) 00298 break; 00299 00300 /* skip . and .. */ 00301 if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 00302 continue; 00303 00304 /* build the full path of the file into "fsalpath */ 00305 if(FSAL_IS_ERROR 00306 (st = 00307 FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, 00308 &(p_pdirent[*p_nb_entries].name)))) 00309 ReturnStatus(st, INDEX_FSAL_readdir); 00310 00311 p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask; 00312 st = xfsfsal_stat_by_name((fsal_op_context_t *)&(p_dir_descriptor->context), 00313 p_dir_descriptor->fd, dp->d_name, 00314 &p_pdirent[*p_nb_entries].handle, 00315 &p_pdirent[*p_nb_entries].attributes); 00316 00317 if(FSAL_IS_ERROR(st)) 00318 ReturnStatus(st, INDEX_FSAL_readdir); 00319 00320 ((xfsfsal_cookie_t *) (&p_pdirent[*p_nb_entries].cookie))->data.cookie = dp->d_off; 00321 p_pdirent[*p_nb_entries].nextentry = NULL; 00322 if(*p_nb_entries) 00323 p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]); 00324 00325 memcpy((char *)p_end_position, (char *)&p_pdirent[*p_nb_entries].cookie, 00326 sizeof(xfsfsal_cookie_t)); 00327 00328 (*p_nb_entries)++; 00329 } /* for */ 00330 } /* While */ 00331 00332 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); 00333 00334 } 00335 00347 fsal_status_t XFSFSAL_closedir(fsal_dir_t * p_dir_descriptor /* IN */ 00348 ) 00349 { 00350 00351 int rc; 00352 00353 /* sanity checks */ 00354 if(!p_dir_descriptor) 00355 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); 00356 00357 rc = close(((xfsfsal_dir_t *)p_dir_descriptor)->fd); 00358 if(rc != 0) 00359 Return(posix2fsal_error(errno), errno, INDEX_FSAL_closedir); 00360 00361 /* fill dir_descriptor with zeros */ 00362 memset(p_dir_descriptor, 0, sizeof(xfsfsal_dir_t)); 00363 00364 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); 00365 00366 }