/* * This function adds an entry in the database */ fsal_status_t fsal_internal_posixdb_add_entry(fsal_posixdb_conn * p_conn, fsal_name_t * p_filename, fsal_posixdb_fileinfo_t * p_info, posixfsal_handle_t * p_dir_handle, posixfsal_handle_t * p_new_handle) { fsal_posixdb_status_t stdb; if(!p_info || !p_conn || !p_new_handle) /* p_filename & p_dir_handle can be NULL for the root */ ReturnCode(ERR_FSAL_FAULT, 0); add: stdb = fsal_posixdb_add(p_conn, p_info, p_dir_handle, p_filename, p_new_handle); if(stdb.major == ERR_FSAL_POSIXDB_CONSISTENCY) { /* there is already an entry with this path, but it's an inconsistent one */ stdb = fsal_posixdb_deleteHandle(p_conn, p_new_handle); if(FSAL_POSIXDB_IS_ERROR(stdb)) return posixdb2fsal_error(stdb); goto add; } else if(FSAL_POSIXDB_IS_ERROR(stdb)) { return posixdb2fsal_error(stdb); } ReturnCode(ERR_FSAL_NO_ERROR, 0); }
/** * @brief Get the handle of a file, knowing its name and its parent dir * * @param p_context * @param p_parent_dir_handle * Handle of the parent directory * @param p_fsalname * Name of the object * @param p_infofs * Information about the file (taken from the filesystem) to be compared to information stored in database * @param p_object_handle * Handle of the file. * * @return * ERR_FSAL_NOERR, if no error * Anothere error code else. */ fsal_status_t fsal_internal_getInfoFromName(posixfsal_op_context_t * p_context, /* IN */ posixfsal_handle_t * p_parent_dir_handle, /* IN */ fsal_name_t * p_fsalname, /* IN */ fsal_posixdb_fileinfo_t * p_infofs, /* IN */ posixfsal_handle_t * p_object_handle) /* OUT */ { fsal_posixdb_status_t stdb; fsal_status_t st; stdb = fsal_posixdb_getInfoFromName(p_context->p_conn, p_parent_dir_handle, p_fsalname, NULL, p_object_handle); switch (stdb.major) { case ERR_FSAL_POSIXDB_NOERR: /* No error, the object is in the database */ /* check consistency */ if(fsal_posixdb_consistency_check(&(p_object_handle->data.info), p_infofs)) { /* Entry not consistent */ /* Delete the Handle entry, then add a new one (with a Parent entry) */ stdb = fsal_posixdb_deleteHandle(p_context->p_conn, p_object_handle); if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) return st; /* don't break, add a new entry */ } else { break; } case ERR_FSAL_POSIXDB_NOENT: /* object not in the database, add a new entry */ st = fsal_internal_posixdb_add_entry(p_context->p_conn, p_fsalname, p_infofs, p_parent_dir_handle, p_object_handle); if(FSAL_IS_ERROR(st)) return st; break; default: /* error */ if(FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) return st; } ReturnCode(ERR_FSAL_NO_ERROR, 0); }
/** * FSAL_readdir : * Read the entries of an opened directory. * * \param dir_descriptor (input): * Pointer to the directory descriptor filled by FSAL_opendir. * \param start_position (input): * Cookie that indicates the first object to be read during * this readdir operation. * This should be : * - FSAL_READDIR_FROM_BEGINNING for reading the content * of the directory from the beginning. * - The end_position parameter returned by the previous * call to FSAL_readdir. * \param get_attr_mask (input) * Specify the set of attributes to be retrieved for directory entries. * \param buffersize (input) * The size (in bytes) of the buffer where * the direntries are to be stored. * \param pdirent (output) * Adresse of the buffer where the direntries are to be stored. * \param end_position (output) * Cookie that indicates the current position in the directory. * \param nb_entries (output) * Pointer to the number of entries read during the call. * \param end_of_dir (output) * Pointer to a boolean that indicates if the end of dir * has been reached during the call. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t POSIXFSAL_readdir(fsal_dir_t * dir_descriptor, /* IN */ fsal_cookie_t start_pos, /* IN */ fsal_attrib_mask_t get_attr_mask, /* IN */ fsal_mdsize_t buffersize, /* IN */ fsal_dirent_t * p_pdirent, /* OUT */ fsal_cookie_t * end_position, /* OUT */ fsal_count_t * p_nb_entries, /* OUT */ fsal_boolean_t * p_end_of_dir /* OUT */ ) { posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; posixfsal_cookie_t start_position, telldir_pos; posixfsal_cookie_t * p_end_position = (posixfsal_cookie_t *) end_position; fsal_status_t st; fsal_posixdb_status_t stdb; fsal_count_t max_dir_entries; struct dirent *dp; struct dirent dpe; struct stat buffstat; fsal_path_t fsalpath; fsal_posixdb_fileinfo_t infofs; int rc; /*****************/ /* sanity checks */ /*****************/ if(!p_dir_descriptor || !p_pdirent || !p_end_position || !p_nb_entries || !p_end_of_dir) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); max_dir_entries = (buffersize / sizeof(fsal_dirent_t)); /***************************/ /* seek into the directory */ /***************************/ memcpy ( (char *)&start_position.data.cookie, (char *)&start_pos.data, sizeof( off_t ) ) ; errno = 0; if(start_position.data.cookie == 0) { rewinddir(p_dir_descriptor->p_dir); rc = errno; } else { seekdir(p_dir_descriptor->p_dir, start_position.data.cookie); rc = errno; } if(rc) { st.major = posix2fsal_error(rc); st.minor = rc; goto readdir_error; } /************************/ /* browse the directory */ /************************/ *p_nb_entries = 0; while(*p_nb_entries < max_dir_entries) { /***********************/ /* read the next entry */ /***********************/ TakeTokenFSCall(); rc = readdir_r(p_dir_descriptor->p_dir, &dpe, &dp); ReleaseTokenFSCall(); if(rc) { st.major = posix2fsal_error(errno); st.minor = errno; goto readdir_error; } /* End of directory */ if(!dp) { *p_end_of_dir = 1; break; } /***********************************/ /* Get information about the entry */ /***********************************/ /* build the full path of the file into "fsalpath */ if(FSAL_IS_ERROR (st = FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, &(p_pdirent[*p_nb_entries].name)))) goto readdir_error; memcpy(&fsalpath, &(p_dir_descriptor->path), sizeof(fsal_path_t)); st = fsal_internal_appendFSALNameToFSALPath(&fsalpath, &(p_pdirent[*p_nb_entries].name)); if(FSAL_IS_ERROR(st)) goto readdir_error; /* get object info */ TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat); ReleaseTokenFSCall(); if(rc) { st.major = posix2fsal_error(errno); st.minor = errno; goto readdir_error; } if(FSAL_IS_ERROR(st = fsal_internal_posix2posixdb_fileinfo(&buffstat, &infofs))) goto readdir_error; /********************/ /* fills the handle */ /********************/ /* check for "." and ".." */ if(!strcmp(dp->d_name, ".")) { memcpy(&(p_pdirent[*p_nb_entries].handle), &(p_dir_descriptor->handle), sizeof(posixfsal_handle_t)); } else if(!strcmp(dp->d_name, "..")) { stdb = fsal_posixdb_getParentDirHandle(p_dir_descriptor->context.p_conn, &(p_dir_descriptor->handle), (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle)); if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) goto readdir_error; } else { #ifdef _USE_POSIXDB_READDIR_BLOCK if(p_dir_descriptor->dbentries_count > -1) { /* look for the entry in dbentries */ st = fsal_internal_getInfoFromChildrenList(&(p_dir_descriptor->context), &(p_dir_descriptor->handle), &(p_pdirent[*p_nb_entries].name), &infofs, p_dir_descriptor->p_dbentries, p_dir_descriptor-> dbentries_count, &(p_pdirent[*p_nb_entries]. handle)); } else #endif { /* get handle for the entry */ st = fsal_internal_getInfoFromName(&(p_dir_descriptor->context), &(p_dir_descriptor->handle), &(p_pdirent[*p_nb_entries].name), &infofs, (posixfsal_handle_t *) &(p_pdirent[*p_nb_entries].handle)); } if(FSAL_IS_ERROR(st)) goto readdir_error; } /* end of name check for "." and ".." */ /************************ * Fills the attributes * ************************/ p_pdirent[*p_nb_entries].attributes.asked_attributes = get_attr_mask; st = posix2fsal_attributes(&buffstat, &(p_pdirent[*p_nb_entries].attributes)); if(FSAL_IS_ERROR(st)) goto readdir_error; /* * **/ telldir_pos.data.cookie = telldir(p_dir_descriptor->p_dir); memcpy(&p_pdirent[*p_nb_entries].cookie, &telldir_pos, sizeof(fsal_cookie_t)); p_pdirent[*p_nb_entries].nextentry = NULL; if(*p_nb_entries) p_pdirent[*p_nb_entries - 1].nextentry = &(p_pdirent[*p_nb_entries]); memcpy(p_end_position, &p_pdirent[*p_nb_entries].cookie, sizeof(fsal_cookie_t)); (*p_nb_entries)++; }; Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); /* return error, and free what must be freed */ readdir_error: Return(st.major, st.minor, INDEX_FSAL_readdir); }
/** * @brief Get the handle of a file from a fsal_posixdb_child array, knowing its name * * @param p_context * @param p_parent_dir_handle * Handle of the parent directory * @param p_fsalname * Name of the object * @param p_infofs * Information about the file (taken from the filesystem) to be compared to information stored in database * @param p_children * fsal_posixdb_child array (that contains the entries of the directory stored in the db) * @param p_object_handle * Handle of the file. * * @return * ERR_FSAL_NOERR, if no error * Anothere error code else. */ fsal_status_t fsal_internal_getInfoFromChildrenList(posixfsal_op_context_t * p_context, /* IN */ posixfsal_handle_t * p_parent_dir_handle, /* IN */ fsal_name_t * p_fsalname, /* IN */ fsal_posixdb_fileinfo_t * p_infofs, /* IN */ fsal_posixdb_child * p_children, /* IN */ unsigned int children_count, /* IN */ posixfsal_handle_t * p_object_handle) /* OUT */ { fsal_posixdb_status_t stdb; fsal_status_t st; int cmp = -1; /* when no children is available */ unsigned int count; /* sanity check */ if(!p_context || !p_parent_dir_handle || !p_fsalname || (!p_children && children_count) || !p_object_handle) ReturnCode(ERR_FSAL_FAULT, 0); /* check if the filename is in the list */ for(count = 0; count < children_count; count++) { cmp = FSAL_namecmp(p_fsalname, &(p_children[count].name)); if(!cmp) break; /* maybe a sorted list could give better result */ } switch (cmp) { case 0: /* Entry found : check consistency */ if(fsal_posixdb_consistency_check(&(p_children[count].handle.data.info), p_infofs)) { /* Entry not consistent */ /* Delete the Handle entry, then add a new one (with a Parent entry) */ stdb = fsal_posixdb_deleteHandle(p_context->p_conn, &(p_children[count].handle)); if(FSAL_POSIXDB_IS_ERROR(stdb) && FSAL_IS_ERROR(st = posixdb2fsal_error(stdb))) return st; /* don't break, add a new entry */ } else { memcpy(p_object_handle, &(p_children[count].handle), sizeof(posixfsal_handle_t)); break; } default: /* not found ! Add it */ st = fsal_internal_posixdb_add_entry(p_context->p_conn, p_fsalname, p_infofs, p_parent_dir_handle, p_object_handle); if(FSAL_IS_ERROR(st)) return st; } ReturnCode(ERR_FSAL_NO_ERROR, 0); }
/** * Get a valid path associated to an handle. * The function selects many paths from the DB and return the first valid one. If is_dir is set, then only 1 path will be constructed from the database. */ fsal_status_t fsal_internal_getPathFromHandle(posixfsal_op_context_t * p_context, /* IN */ posixfsal_handle_t * p_handle, /* IN */ int is_dir, /* IN */ fsal_path_t * p_fsalpath, /* OUT */ struct stat *p_buffstat /* OUT */ ) { fsal_status_t status; fsal_posixdb_status_t statusdb; int rc, errsv, count, i; fsal_posixdb_fileinfo_t infofs; fsal_path_t paths[global_fs_info.maxlink]; if(!p_context || !p_handle || !p_fsalpath) ReturnCode(ERR_FSAL_FAULT, 0); /* if there is a path in the posixfsal_handle_t variable, then try to use it instead of querying the database for it */ /* Read the path from the Handle. If it's valid & coherent, then no need to query the database ! */ /* if !p_buffstat, we don't need to check the path */ statusdb = fsal_posixdb_getInfoFromHandle(p_context->p_conn, p_handle, paths, (is_dir ? 1 : global_fs_info.maxlink), &count); if(FSAL_POSIXDB_IS_ERROR(statusdb) && FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb))) return status; /* if !p_buffstat, then we do not stat the path to test if file is valid */ if(p_buffstat) { for(i = 0; i < count; i++) { TakeTokenFSCall(); rc = lstat(paths[i].path, p_buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) { /* error : delete the bad path from the database */ char dirc[FSAL_MAX_PATH_LEN]; char basec[FSAL_MAX_PATH_LEN]; fsal_path_t parentdir; fsal_name_t filename; posixfsal_handle_t parenthdl; char *dname, *bname; /* split /path/to/filename in /path/to & filename */ strncpy(dirc, paths[i].path, FSAL_MAX_PATH_LEN); strncpy(basec, paths[i].path, FSAL_MAX_PATH_LEN); dname = dirname(dirc); bname = basename(basec); status = FSAL_str2path(dname, FSAL_MAX_PATH_LEN, &parentdir); status = FSAL_str2name(bname, FSAL_MAX_NAME_LEN, &filename); /* get the handle of /path/to */ status = POSIXFSAL_lookupPath(&parentdir, p_context, &parenthdl, NULL); if(!FSAL_IS_ERROR(status)) { statusdb = fsal_posixdb_delete(p_context->p_conn, &parenthdl, &filename, NULL); /* no need to check if there was an error, because it doesn't change the behavior of the function */ } } else { /* no error */ FSAL_pathcpy(p_fsalpath, &(paths[0])); break; } } if(i == count) ReturnCode(ERR_FSAL_STALE, 0); /* check consistency */ status = fsal_internal_posix2posixdb_fileinfo(p_buffstat, &infofs); if(FSAL_IS_ERROR(status)) return status; if(fsal_posixdb_consistency_check(&(p_handle->data.info), &infofs)) { /* not consistent !! */ /* delete the stale handle */ statusdb = fsal_posixdb_deleteHandle(p_context->p_conn, p_handle); if(FSAL_POSIXDB_IS_ERROR(statusdb) && FSAL_IS_ERROR(status = posixdb2fsal_error(statusdb))) return status; ReturnCode(ERR_FSAL_STALE, 0); } } else { /* @TODO : check that there si at liste 1 path */ FSAL_pathcpy(p_fsalpath, &(paths[0])); } ReturnCode(ERR_FSAL_NO_ERROR, 0); }