nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00015 #define FSAL_INTERNAL_C 00016 #ifdef HAVE_CONFIG_H 00017 #include "config.h" 00018 #endif 00019 00020 #include "fsal.h" 00021 #include "fsal_internal.h" 00022 #include "posixdb_consistency.h" 00023 #include "abstract_mem.h" 00024 #include "SemN.h" 00025 #include "fsal_convert.h" 00026 #include <libgen.h> /* used for 'dirname' */ 00027 00028 #include <pthread.h> 00029 #include <string.h> 00030 #include <mntent.h> 00031 00032 /* credential lifetime (1h) */ 00033 fsal_uint_t CredentialLifetime = 3600; 00034 00035 /* static filesystem info. 00036 * The access is thread-safe because 00037 * it is read-only, except during initialization. 00038 */ 00039 fsal_staticfsinfo_t global_fs_info; 00040 fsal_posixdb_conn_params_t global_posixdb_params; 00041 00042 /* filesystem info for HPSS */ 00043 static fsal_staticfsinfo_t default_posix_info = { 00044 0xFFFFFFFFFFFFFFFFLL, /* max file size (64bits) */ 00045 _POSIX_LINK_MAX, /* max links */ 00046 FSAL_MAX_NAME_LEN, /* max filename */ 00047 FSAL_MAX_PATH_LEN, /* min filename */ 00048 TRUE, /* no_trunc */ 00049 TRUE, /* chown restricted */ 00050 FALSE, /* case insensitivity */ 00051 TRUE, /* case preserving */ 00052 FSAL_EXPTYPE_PERSISTENT, /* FH expire type */ 00053 TRUE, /* hard link support */ 00054 TRUE, /* symlink support */ 00055 FALSE, /* lock management */ 00056 FALSE, /* lock owners */ 00057 FALSE, /* async blocking locks */ 00058 TRUE, /* named attributes */ 00059 TRUE, /* handles are unique and persistent */ 00060 {10, 0}, /* Duration of lease at FS in seconds */ 00061 FSAL_ACLSUPPORT_ALLOW, /* ACL support */ 00062 TRUE, /* can change times */ 00063 TRUE, /* homogenous */ 00064 POSIX_SUPPORTED_ATTRIBUTES, /* supported attributes */ 00065 0, /* maxread size */ 00066 0, /* maxwrite size */ 00067 0, /* default umask */ 00068 0, /* cross junctions */ 00069 0400, /* default access rights for xattrs: root=RW, owner=R */ 00070 0, /* default access check support in FSAL */ 00071 0, /* default share reservation support in FSAL */ 00072 0 /* default share reservation support with open owners in FSAL */ 00073 }; 00074 00075 /* variables for limiting the calls to the filesystem */ 00076 static int limit_calls = FALSE; 00077 semaphore_t sem_fs_calls; 00078 00079 /* threads keys for stats */ 00080 static pthread_key_t key_stats; 00081 static pthread_once_t once_key = PTHREAD_ONCE_INIT; 00082 00083 /* init keys */ 00084 static void init_keys(void) 00085 { 00086 if(pthread_key_create(&key_stats, NULL) == -1) 00087 LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_KEY_CREATE, errno); 00088 00089 return; 00090 } /* init_keys */ 00091 00103 void fsal_increment_nbcall(int function_index, fsal_status_t status) 00104 { 00105 00106 fsal_statistics_t *bythread_stat = NULL; 00107 00108 /* verify index */ 00109 00110 if(function_index >= FSAL_NB_FUNC) 00111 return; 00112 00113 /* first, we init the keys if this is the first time */ 00114 00115 if(pthread_once(&once_key, init_keys) != 0) 00116 { 00117 LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno); 00118 return; 00119 } 00120 00121 /* we get the specific value */ 00122 00123 bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats); 00124 00125 /* we allocate stats if this is the first time */ 00126 00127 if(bythread_stat == NULL) 00128 { 00129 int i; 00130 00131 bythread_stat = gsh_malloc(sizeof(fsal_statistics_t)); 00132 00133 if(bythread_stat == NULL) 00134 { 00135 LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM); 00136 return; 00137 } 00138 00139 /* inits the struct */ 00140 00141 for(i = 0; i < FSAL_NB_FUNC; i++) 00142 { 00143 bythread_stat->func_stats.nb_call[i] = 0; 00144 bythread_stat->func_stats.nb_success[i] = 0; 00145 bythread_stat->func_stats.nb_err_retryable[i] = 0; 00146 bythread_stat->func_stats.nb_err_unrecover[i] = 0; 00147 } 00148 00149 /* set the specific value */ 00150 pthread_setspecific(key_stats, (void *)bythread_stat); 00151 00152 } 00153 00154 /* we increment the values */ 00155 00156 if(bythread_stat) 00157 { 00158 bythread_stat->func_stats.nb_call[function_index]++; 00159 00160 if(!FSAL_IS_ERROR(status)) 00161 bythread_stat->func_stats.nb_success[function_index]++; 00162 else if(status.major == ERR_FSAL_DELAY) 00163 bythread_stat->func_stats.nb_err_retryable[function_index]++; 00164 else 00165 bythread_stat->func_stats.nb_err_unrecover[function_index]++; 00166 } 00167 00168 return; 00169 } 00170 00181 void fsal_internal_getstats(fsal_statistics_t * output_stats) 00182 { 00183 00184 fsal_statistics_t *bythread_stat = NULL; 00185 00186 /* first, we init the keys if this is the first time */ 00187 if(pthread_once(&once_key, init_keys) != 0) 00188 { 00189 LogError(COMPONENT_FSAL, ERR_SYS, ERR_PTHREAD_ONCE, errno); 00190 return; 00191 } 00192 00193 /* we get the specific value */ 00194 bythread_stat = (fsal_statistics_t *) pthread_getspecific(key_stats); 00195 00196 /* we allocate stats if this is the first time */ 00197 if(bythread_stat == NULL) 00198 { 00199 int i; 00200 00201 bythread_stat = gsh_malloc(sizeof(fsal_statistics_t)); 00202 00203 if(bythread_stat == NULL) 00204 { 00205 LogError(COMPONENT_FSAL, ERR_SYS, ERR_MALLOC, ENOMEM); 00206 return; 00207 } 00208 /* inits the struct */ 00209 for(i = 0; i < FSAL_NB_FUNC; i++) 00210 { 00211 bythread_stat->func_stats.nb_call[i] = 0; 00212 bythread_stat->func_stats.nb_success[i] = 0; 00213 bythread_stat->func_stats.nb_err_retryable[i] = 0; 00214 bythread_stat->func_stats.nb_err_unrecover[i] = 0; 00215 } 00216 00217 /* set the specific value */ 00218 pthread_setspecific(key_stats, (void *)bythread_stat); 00219 00220 } 00221 00222 if(output_stats) 00223 (*output_stats) = (*bythread_stat); 00224 00225 return; 00226 00227 } 00228 00239 void fsal_internal_SetCredentialLifetime(fsal_uint_t lifetime_in) 00240 { 00241 CredentialLifetime = lifetime_in; 00242 } 00243 00247 void TakeTokenFSCall() 00248 { 00249 /* no limits */ 00250 if(limit_calls == FALSE) 00251 return; 00252 00253 /* there is a limit */ 00254 semaphore_P(&sem_fs_calls); 00255 00256 } 00257 00258 void ReleaseTokenFSCall() 00259 { 00260 /* no limits */ 00261 if(limit_calls == FALSE) 00262 return; 00263 00264 /* there is a limit */ 00265 semaphore_V(&sem_fs_calls); 00266 00267 } 00268 00269 /* 00270 * This function initializes shared variables of the fsal. 00271 */ 00272 fsal_status_t fsal_internal_init_global(fsal_init_info_t * fsal_info, 00273 fs_common_initinfo_t * fs_common_info, 00274 posixfs_specific_initinfo_t * fs_specific_info) 00275 { 00276 /* sanity check */ 00277 if(!fsal_info || !fs_common_info || !fs_specific_info) 00278 ReturnCode(ERR_FSAL_FAULT, 0); 00279 00280 /* inits FS call semaphore */ 00281 if(fsal_info->max_fs_calls > 0) 00282 { 00283 int rc; 00284 00285 limit_calls = TRUE; 00286 00287 rc = semaphore_init(&sem_fs_calls, fsal_info->max_fs_calls); 00288 00289 if(rc != 0) 00290 ReturnCode(ERR_FSAL_SERVERFAULT, rc); 00291 00292 LogDebug(COMPONENT_FSAL, 00293 "FSAL INIT: Max simultaneous calls to filesystem is limited to %u.", 00294 fsal_info->max_fs_calls); 00295 00296 } 00297 else 00298 { 00299 LogDebug(COMPONENT_FSAL, 00300 "FSAL INIT: Max simultaneous calls to filesystem is unlimited."); 00301 } 00302 00303 /* setting default values. */ 00304 global_fs_info = default_posix_info; 00305 00306 display_fsinfo(&default_posix_info); 00307 00308 /* Analyzing fs_common_info struct */ 00309 00310 if((fs_common_info->behaviors.maxfilesize != FSAL_INIT_FS_DEFAULT) || 00311 (fs_common_info->behaviors.maxlink != FSAL_INIT_FS_DEFAULT) || 00312 (fs_common_info->behaviors.maxnamelen != FSAL_INIT_FS_DEFAULT) || 00313 (fs_common_info->behaviors.maxpathlen != FSAL_INIT_FS_DEFAULT) || 00314 (fs_common_info->behaviors.no_trunc != FSAL_INIT_FS_DEFAULT) || 00315 (fs_common_info->behaviors.case_insensitive != FSAL_INIT_FS_DEFAULT) || 00316 (fs_common_info->behaviors.case_preserving != FSAL_INIT_FS_DEFAULT) || 00317 (fs_common_info->behaviors.named_attr != FSAL_INIT_FS_DEFAULT) || 00318 (fs_common_info->behaviors.lease_time != FSAL_INIT_FS_DEFAULT) || 00319 (fs_common_info->behaviors.supported_attrs != FSAL_INIT_FS_DEFAULT) || 00320 (fs_common_info->behaviors.homogenous != FSAL_INIT_FS_DEFAULT)) 00321 ReturnCode(ERR_FSAL_NOTSUPP, 0); 00322 00323 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, symlink_support); 00324 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, link_support); 00325 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support); 00326 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_owner); 00327 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, lock_support_async_block); 00328 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, cansettime); 00329 00330 SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxread); 00331 SET_INTEGER_PARAM(global_fs_info, fs_common_info, maxwrite); 00332 00333 SET_BITMAP_PARAM(global_fs_info, fs_common_info, umask); 00334 00335 SET_BOOLEAN_PARAM(global_fs_info, fs_common_info, auth_exportpath_xdev); 00336 00337 SET_BITMAP_PARAM(global_fs_info, fs_common_info, xattr_access_rights); 00338 00339 /* setting global database parameters */ 00340 global_posixdb_params = fs_specific_info->dbparams; 00341 00342 LogFullDebug(COMPONENT_FSAL, 00343 "Supported attributes constant = 0x%llX.", 00344 POSIX_SUPPORTED_ATTRIBUTES); 00345 00346 LogFullDebug(COMPONENT_FSAL, 00347 "Supported attributes default = 0x%llX.", 00348 default_posix_info.supported_attrs); 00349 00350 LogDebug(COMPONENT_FSAL, 00351 "FSAL INIT: Supported attributes mask = 0x%llX.", 00352 global_fs_info.supported_attrs); 00353 00354 /* initialize database cache */ 00355 if(fsal_posixdb_cache_init()) 00356 ReturnCode(ERR_FSAL_FAULT, 0); 00357 00358 LogDebug(COMPONENT_FSAL, "global_fs_info {"); 00359 LogDebug(COMPONENT_FSAL, " maxfilesize = %zu ", 00360 global_fs_info.maxfilesize); 00361 LogDebug(COMPONENT_FSAL, " maxlink = %lu ", global_fs_info.maxlink); 00362 LogDebug(COMPONENT_FSAL, " maxnamelen = %lu ", 00363 global_fs_info.maxnamelen); 00364 LogDebug(COMPONENT_FSAL, " maxpathlen = %lu ", 00365 global_fs_info.maxpathlen); 00366 LogDebug(COMPONENT_FSAL, " no_trunc = %d ", global_fs_info.no_trunc); 00367 LogDebug(COMPONENT_FSAL, " chown_restricted = %d ", 00368 global_fs_info.chown_restricted); 00369 LogDebug(COMPONENT_FSAL, " case_insensitive = %d ", 00370 global_fs_info.case_insensitive); 00371 LogDebug(COMPONENT_FSAL, " case_preserving = %d ", 00372 global_fs_info.case_preserving); 00373 LogDebug(COMPONENT_FSAL, " fh_expire_type = %hu ", 00374 global_fs_info.fh_expire_type); 00375 LogDebug(COMPONENT_FSAL, " link_support = %d ", 00376 global_fs_info.link_support); 00377 LogDebug(COMPONENT_FSAL, " symlink_support = %d ", 00378 global_fs_info.symlink_support); 00379 LogDebug(COMPONENT_FSAL, " lock_support = %d ", 00380 global_fs_info.lock_support); 00381 LogDebug(COMPONENT_FSAL, " lock_support_owner = %d ", 00382 global_fs_info.lock_support_owner); 00383 LogDebug(COMPONENT_FSAL, " lock_support_async_block = %d ", 00384 global_fs_info.lock_support_async_block); 00385 LogDebug(COMPONENT_FSAL, " named_attr = %d ", 00386 global_fs_info.named_attr); 00387 LogDebug(COMPONENT_FSAL, " unique_handles = %d ", 00388 global_fs_info.unique_handles); 00389 LogDebug(COMPONENT_FSAL, " acl_support = %hu ", 00390 global_fs_info.acl_support); 00391 LogDebug(COMPONENT_FSAL, " cansettime = %d ", 00392 global_fs_info.cansettime); 00393 LogDebug(COMPONENT_FSAL, " homogenous = %d ", 00394 global_fs_info.homogenous); 00395 LogDebug(COMPONENT_FSAL, " supported_attrs = %llX ", 00396 global_fs_info.supported_attrs); 00397 LogDebug(COMPONENT_FSAL, " maxread = %zu ", 00398 global_fs_info.maxread); 00399 LogDebug(COMPONENT_FSAL, " maxwrite = %zu ", 00400 global_fs_info.maxwrite); 00401 LogDebug(COMPONENT_FSAL, " umask = %X ", global_fs_info.umask); 00402 LogDebug(COMPONENT_FSAL, "}"); 00403 00404 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00405 } 00406 00415 fsal_status_t fsal_internal_posix2posixdb_fileinfo(struct stat *buffstat, 00416 fsal_posixdb_fileinfo_t * info) 00417 { 00418 /* sanity check */ 00419 if(!info || !buffstat) 00420 ReturnCode(ERR_FSAL_FAULT, 0); 00421 00422 memset(info, 0, sizeof(fsal_posixdb_fileinfo_t)); 00423 info->devid = buffstat->st_dev; 00424 info->inode = buffstat->st_ino; 00425 info->nlink = (int)buffstat->st_nlink; 00426 info->ctime = buffstat->st_ctime; 00427 info->ftype = posix2fsal_type(buffstat->st_mode); 00428 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00429 } 00430 00431 /* 00432 * This function adds an entry in the database 00433 */ 00434 fsal_status_t fsal_internal_posixdb_add_entry(fsal_posixdb_conn * p_conn, 00435 fsal_name_t * p_filename, 00436 fsal_posixdb_fileinfo_t * p_info, 00437 posixfsal_handle_t * p_dir_handle, 00438 posixfsal_handle_t * p_new_handle) 00439 { 00440 fsal_posixdb_status_t stdb; 00441 00442 if(!p_info || !p_conn || !p_new_handle) /* p_filename & p_dir_handle can be NULL for the root */ 00443 ReturnCode(ERR_FSAL_FAULT, 0); 00444 00445 add: 00446 stdb = fsal_posixdb_add(p_conn, p_info, p_dir_handle, p_filename, p_new_handle); 00447 00448 if(stdb.major == ERR_FSAL_POSIXDB_CONSISTENCY) 00449 { /* there is already an entry with this path, but it's an inconsistent one */ 00450 stdb = fsal_posixdb_deleteHandle(p_conn, p_new_handle); 00451 if(FSAL_POSIXDB_IS_ERROR(stdb)) 00452 return posixdb2fsal_error(stdb); 00453 goto add; 00454 } 00455 else if(FSAL_POSIXDB_IS_ERROR(stdb)) 00456 { 00457 return posixdb2fsal_error(stdb); 00458 } 00459 00460 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00461 } 00462 00471 fsal_status_t fsal_internal_appendFSALNameToFSALPath(fsal_path_t * p_path, 00472 fsal_name_t * p_name) 00473 { 00474 char *end; 00475 if(!p_path || !p_name) 00476 ReturnCode(ERR_FSAL_FAULT, 0); 00477 00478 end = p_path->path + p_path->len - 1; 00479 if(*end != '/') 00480 { 00481 if(p_path->len + 1 + p_name->len > FSAL_MAX_PATH_LEN) 00482 ReturnCode(ERR_FSAL_NAMETOOLONG, 0); 00483 p_path->len += p_name->len + 1; 00484 end++; 00485 *end = '/'; 00486 end++; 00487 strcpy(end, p_name->name); 00488 } 00489 else 00490 { 00491 if(p_path->len + p_name->len > FSAL_MAX_PATH_LEN) 00492 ReturnCode(ERR_FSAL_NAMETOOLONG, 0); 00493 p_path->len += p_name->len; 00494 end++; 00495 strcpy(end, p_name->name); 00496 } 00497 00498 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00499 } 00500 00505 fsal_status_t fsal_internal_getPathFromHandle(posixfsal_op_context_t * p_context, /* IN */ 00506 posixfsal_handle_t * p_handle, /* IN */ 00507 int is_dir, /* IN */ 00508 fsal_path_t * p_fsalpath, /* OUT */ 00509 struct stat *p_buffstat /* OUT */ ) 00510 { 00511 fsal_status_t status; 00512 fsal_posixdb_status_t statusdb; 00513 int rc, /* errsv, */count, i; 00514 fsal_posixdb_fileinfo_t infofs; 00515 fsal_path_t paths[global_fs_info.maxlink]; 00516 00517 if(!p_context || !p_handle || !p_fsalpath) 00518 ReturnCode(ERR_FSAL_FAULT, 0); 00519 00520 /* if there is a path in the posixfsal_handle_t variable, then try to use it instead of querying the database for it */ 00521 /* Read the path from the Handle. If it's valid & coherent, then no need to query the database ! */ 00522 /* if !p_buffstat, we don't need to check the path */ 00523 statusdb = fsal_posixdb_getInfoFromHandle(p_context->p_conn, 00524 p_handle, 00525 paths, 00526 (is_dir ? 1 : global_fs_info.maxlink), 00527 &count); 00528 if(FSAL_POSIXDB_IS_ERROR(statusdb) 00529 && FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb))) 00530 return status; 00531 00532 /* if !p_buffstat, then we do not stat the path to test if file is valid */ 00533 if(p_buffstat) 00534 { 00535 for(i = 0; i < count; i++) 00536 { 00537 TakeTokenFSCall(); 00538 rc = lstat(paths[i].path, p_buffstat); 00539 /* errsv = errno; */ 00540 ReleaseTokenFSCall(); 00541 00542 if(rc) 00543 { 00544 /* error : delete the bad path from the database */ 00545 char dirc[FSAL_MAX_PATH_LEN]; 00546 char basec[FSAL_MAX_PATH_LEN]; 00547 fsal_path_t parentdir; 00548 fsal_name_t filename; 00549 posixfsal_handle_t parenthdl; 00550 char *dname, *bname; 00551 00552 /* split /path/to/filename in /path/to & filename */ 00553 strncpy(dirc, paths[i].path, FSAL_MAX_PATH_LEN); 00554 strncpy(basec, paths[i].path, FSAL_MAX_PATH_LEN); 00555 dname = dirname(dirc); 00556 bname = basename(basec); 00557 00558 status = FSAL_str2path(dname, FSAL_MAX_PATH_LEN, &parentdir); 00559 status = FSAL_str2name(bname, FSAL_MAX_NAME_LEN, &filename); 00560 00561 /* get the handle of /path/to */ 00562 00563 status = POSIXFSAL_lookupPath(&parentdir, 00564 (fsal_op_context_t *)p_context, 00565 (fsal_handle_t *)&parenthdl, NULL); 00566 00567 if(!FSAL_IS_ERROR(status)) 00568 { 00569 statusdb = 00570 fsal_posixdb_delete(p_context->p_conn, &parenthdl, &filename, NULL); 00571 /* no need to check if there was an error, because it doesn't change the behavior of the function */ 00572 } 00573 00574 } 00575 else 00576 { /* no error */ 00577 FSAL_pathcpy(p_fsalpath, &(paths[0])); 00578 break; 00579 } 00580 } 00581 if(i == count) 00582 ReturnCode(ERR_FSAL_STALE, 0); 00583 00584 /* check consistency */ 00585 status = fsal_internal_posix2posixdb_fileinfo(p_buffstat, &infofs); 00586 if(FSAL_IS_ERROR(status)) 00587 return status; 00588 00589 if(fsal_posixdb_consistency_check(&(p_handle->data.info), &infofs)) 00590 { 00591 /* not consistent !! */ 00592 /* delete the stale handle */ 00593 statusdb = fsal_posixdb_deleteHandle(p_context->p_conn, p_handle); 00594 if(FSAL_POSIXDB_IS_ERROR(statusdb) 00595 && FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb))) 00596 return status; 00597 00598 ReturnCode(ERR_FSAL_STALE, 0); 00599 } 00600 00601 } 00602 else 00603 { 00604 /* @TODO : check that there si at liste 1 path */ 00605 FSAL_pathcpy(p_fsalpath, &(paths[0])); 00606 } 00607 00608 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00609 } 00610 00628 fsal_status_t fsal_internal_getInfoFromName(posixfsal_op_context_t * p_context, /* IN */ 00629 posixfsal_handle_t * p_parent_dir_handle, /* IN */ 00630 fsal_name_t * p_fsalname, /* IN */ 00631 fsal_posixdb_fileinfo_t * p_infofs, /* IN */ 00632 posixfsal_handle_t * p_object_handle) /* OUT */ 00633 { 00634 fsal_posixdb_status_t stdb; 00635 fsal_status_t st; 00636 00637 stdb = fsal_posixdb_getInfoFromName(p_context->p_conn, 00638 p_parent_dir_handle, 00639 p_fsalname, NULL, p_object_handle); 00640 switch (stdb.major) 00641 { 00642 case ERR_FSAL_POSIXDB_NOERR: 00643 /* No error, the object is in the database */ 00644 /* check consistency */ 00645 if(fsal_posixdb_consistency_check(&(p_object_handle->data.info), p_infofs)) 00646 { 00647 /* Entry not consistent */ 00648 /* Delete the Handle entry, then add a new one (with a Parent entry) */ 00649 stdb = fsal_posixdb_deleteHandle(p_context->p_conn, p_object_handle); 00650 if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) 00651 return st; 00652 /* don't break, add a new entry */ 00653 } 00654 else 00655 { 00656 break; 00657 } 00658 case ERR_FSAL_POSIXDB_NOENT: 00659 /* object not in the database, add a new entry */ 00660 st = fsal_internal_posixdb_add_entry(p_context->p_conn, 00661 p_fsalname, 00662 p_infofs, 00663 p_parent_dir_handle, p_object_handle); 00664 if(FSAL_IS_ERROR(st)) 00665 return st; 00666 break; 00667 default: 00668 /* error */ 00669 if(FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) 00670 return st; 00671 } 00672 00673 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00674 } 00675 00695 fsal_status_t fsal_internal_getInfoFromChildrenList(posixfsal_op_context_t * p_context, /* IN */ 00696 posixfsal_handle_t * p_parent_dir_handle, /* IN */ 00697 fsal_name_t * p_fsalname, /* IN */ 00698 fsal_posixdb_fileinfo_t * p_infofs, /* IN */ 00699 fsal_posixdb_child * p_children, /* IN */ 00700 unsigned int children_count, /* IN */ 00701 posixfsal_handle_t * p_object_handle) /* OUT */ 00702 { 00703 fsal_posixdb_status_t stdb; 00704 fsal_status_t st; 00705 int cmp = -1; /* when no children is available */ 00706 unsigned int count; 00707 00708 /* sanity check */ 00709 if(!p_context || !p_parent_dir_handle || !p_fsalname || (!p_children && children_count) 00710 || !p_object_handle) 00711 ReturnCode(ERR_FSAL_FAULT, 0); 00712 00713 /* check if the filename is in the list */ 00714 for(count = 0; count < children_count; count++) 00715 { 00716 cmp = FSAL_namecmp(p_fsalname, &(p_children[count].name)); 00717 if(!cmp) 00718 break; 00719 /* maybe a sorted list could give better result */ 00720 } 00721 00722 switch (cmp) 00723 { 00724 case 0: 00725 /* Entry found : check consistency */ 00726 00727 if(fsal_posixdb_consistency_check(&(p_children[count].handle.data.info), p_infofs)) 00728 { 00729 /* Entry not consistent */ 00730 /* Delete the Handle entry, then add a new one (with a Parent entry) */ 00731 stdb = 00732 fsal_posixdb_deleteHandle(p_context->p_conn, &(p_children[count].handle)); 00733 00734 if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) 00735 return st; 00736 00737 /* don't break, add a new entry */ 00738 00739 } 00740 else 00741 { 00742 memcpy(p_object_handle, &(p_children[count].handle), 00743 sizeof(posixfsal_handle_t)); 00744 break; 00745 } 00746 00747 default: 00748 /* not found ! Add it */ 00749 st = fsal_internal_posixdb_add_entry(p_context->p_conn, 00750 p_fsalname, 00751 p_infofs, 00752 p_parent_dir_handle, p_object_handle); 00753 if(FSAL_IS_ERROR(st)) 00754 return st; 00755 } 00756 00757 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00758 } 00759 00760 /* 00761 Check the access from an existing fsal_attrib_list_t or struct stat 00762 */ 00763 /* XXX : ACL */ 00764 fsal_status_t fsal_internal_testAccess(posixfsal_op_context_t * p_context, /* IN */ 00765 fsal_accessflags_t access_type, /* IN */ 00766 struct stat * p_buffstat, /* IN */ 00767 fsal_attrib_list_t * p_object_attributes /* IN */ ) 00768 { 00769 fsal_accessflags_t missing_access; 00770 unsigned int is_grp, i; 00771 fsal_uid_t uid; 00772 fsal_gid_t gid; 00773 fsal_accessmode_t mode; 00774 00775 /* sanity checks. */ 00776 00777 if((!p_object_attributes && !p_buffstat) || !p_context) 00778 ReturnCode(ERR_FSAL_FAULT, 0); 00779 00780 /* If the FSAL_F_OK flag is set, returns ERR INVAL */ 00781 00782 if(access_type & FSAL_F_OK) 00783 ReturnCode(ERR_FSAL_INVAL, 0); 00784 00785 /* test root access */ 00786 00787 if(p_context->credential.user == 0) 00788 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00789 00790 /* unsatisfied flags */ 00791 00792 missing_access = FSAL_MODE_MASK(access_type); /* only modes, no ACLs here */ 00793 00794 if(p_object_attributes) 00795 { 00796 uid = p_object_attributes->owner; 00797 gid = p_object_attributes->group; 00798 mode = p_object_attributes->mode; 00799 } 00800 else 00801 { 00802 uid = p_buffstat->st_uid; 00803 gid = p_buffstat->st_gid; 00804 mode = unix2fsal_mode(p_buffstat->st_mode); 00805 } 00806 00807 /* Test if file belongs to user. */ 00808 00809 if(p_context->credential.user == uid) 00810 { 00811 LogFullDebug(COMPONENT_FSAL, "File belongs to user %d", uid); 00812 00813 if(mode & FSAL_MODE_RUSR) 00814 missing_access &= ~FSAL_R_OK; 00815 00816 if(mode & FSAL_MODE_WUSR) 00817 missing_access &= ~FSAL_W_OK; 00818 00819 if(mode & FSAL_MODE_XUSR) 00820 missing_access &= ~FSAL_X_OK; 00821 00822 if((missing_access & FSAL_OWNER_OK) != 0) 00823 missing_access = 0; 00824 00825 if(missing_access == 0) 00826 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00827 else 00828 ReturnCode(ERR_FSAL_ACCESS, 0); 00829 } 00830 00831 /* FSAL_OWNER_OK allows overriding checks if the file is owned by the 00832 * requester. It shouldn't take part in any further tests */ 00833 missing_access &= ~FSAL_OWNER_OK; 00834 00835 /* Test if the file belongs to user's group. */ 00836 00837 is_grp = (p_context->credential.group == gid); 00838 00839 if(is_grp) 00840 LogFullDebug(COMPONENT_FSAL, "File belongs to user's group %d", 00841 p_context->credential.group); 00842 00843 /* Test if file belongs to alt user's groups */ 00844 00845 if(!is_grp) 00846 { 00847 for(i = 0; i < p_context->credential.nbgroups; i++) 00848 { 00849 is_grp = (p_context->credential.alt_groups[i] == gid); 00850 00851 if(is_grp) 00852 LogFullDebug(COMPONENT_FSAL, 00853 "File belongs to user's alt group %d", 00854 p_context->credential.alt_groups[i]); 00855 00856 // exits loop if found 00857 if(is_grp) 00858 break; 00859 } 00860 } 00861 00862 /* finally apply group rights */ 00863 00864 if(is_grp) 00865 { 00866 if(mode & FSAL_MODE_RGRP) 00867 missing_access &= ~FSAL_R_OK; 00868 00869 if(mode & FSAL_MODE_WGRP) 00870 missing_access &= ~FSAL_W_OK; 00871 00872 if(mode & FSAL_MODE_XGRP) 00873 missing_access &= ~FSAL_X_OK; 00874 00875 if(missing_access == 0) 00876 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00877 else 00878 ReturnCode(ERR_FSAL_ACCESS, 0); 00879 00880 } 00881 00882 /* test other perms */ 00883 00884 if(mode & FSAL_MODE_ROTH) 00885 missing_access &= ~FSAL_R_OK; 00886 00887 if(mode & FSAL_MODE_WOTH) 00888 missing_access &= ~FSAL_W_OK; 00889 00890 if(mode & FSAL_MODE_XOTH) 00891 missing_access &= ~FSAL_X_OK; 00892 00893 /* XXX ACLs. */ 00894 00895 if(missing_access == 0) 00896 ReturnCode(ERR_FSAL_NO_ERROR, 0); 00897 else 00898 ReturnCode(ERR_FSAL_ACCESS, 0); 00899 00900 } 00901 00902 int fsal_internal_path2fsname(char *rpath, char *fs_spec) 00903 { 00904 FILE *fp; 00905 struct mntent mnt; 00906 struct mntent *pmnt; 00907 char work[MAXPATHLEN]; 00908 char mntdir[MAXPATHLEN]; 00909 00910 size_t pathlen, outlen; 00911 int rc = -1; 00912 00913 pathlen = 0; 00914 outlen = 0; 00915 00916 if(!rpath || !fs_spec) 00917 return -1; 00918 00919 fp = setmntent(MOUNTED, "r"); 00920 00921 if(fp == NULL) 00922 return -1; 00923 00924 while((pmnt = getmntent_r(fp, &mnt, work, MAXPATHLEN)) != NULL) 00925 { 00926 /* get the longer path that matches export path */ 00927 if(mnt.mnt_dir != NULL) 00928 { 00929 pathlen = strlen(mnt.mnt_dir); 00930 00931 if((pathlen > outlen) && !strcmp(mnt.mnt_dir, "/")) 00932 { 00933 outlen = pathlen; 00934 strncpy(mntdir, mnt.mnt_dir, MAXPATHLEN); 00935 strncpy(fs_spec, mnt.mnt_fsname, MAXPATHLEN); 00936 } 00937 /* in other cases, the filesystem must be <mountpoint>/<smthg> or <mountpoint>\0 */ 00938 else if((pathlen > outlen) && 00939 !strncmp(rpath, mnt.mnt_dir, pathlen) && 00940 ((rpath[pathlen] == '/') || (rpath[pathlen] == '\0'))) 00941 { 00942 /* LogFullDebug(COMPONENT_FSAL, "%s is under mountpoint %s, type=%s, fs=%s\n", 00943 rpath, mnt.mnt_dir, mnt.mnt_type, mnt.mnt_fsname); */ 00944 00945 outlen = pathlen; 00946 strncpy(mntdir, mnt.mnt_dir, MAXPATHLEN); 00947 strncpy(fs_spec, mnt.mnt_fsname, MAXPATHLEN); 00948 rc = 0; 00949 } 00950 } 00951 00952 } 00953 00954 endmntent(fp); 00955 return rc; 00956 } /* fsal_internal_path2fsname */