nfs-ganesha 1.4

fsal_internal.c

Go to the documentation of this file.
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 */