fsal_posixdb_status_t fsal_posixdb_delete(fsal_posixdb_conn * p_conn, /* IN */ posixfsal_handle_t * p_parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ fsal_posixdb_fileinfo_t * p_object_info /* IN */ ) { result_handle_t res; fsal_posixdb_status_t st; char query[2048]; /******************* * 1/ sanity check * *******************/ if(!p_conn || !p_parent_directory_handle || !p_filename) ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); BeginTransaction(p_conn); /******************************* * 2/ we check the file exists * *******************************/ snprintf(query, 2048, "SELECT Parent.handleid, Parent.handlets, " "Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid " "AND Parent.handlets=Handle.handlets " "WHERE handleidparent=%llu AND handletsparent=%u AND name='%s' " "FOR UPDATE", p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts, p_filename->name); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; if(mysql_num_rows(res) != 1) { /* parent entry not found */ mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); } mysql_free_result(res); /*********************************************** * 3/ Get information about the file to delete * ***********************************************/ st = fsal_posixdb_internal_delete(p_conn, p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts, p_filename->name, p_object_info); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; return EndTransaction(p_conn); rollback: RollbackTransaction(p_conn); return st; }
/* * 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); }
void display_directory(fsal_posixdb_conn * p_conn, posixfsal_handle_t * p_handle_parent, char *basedir) { fsal_posixdb_child *p_children; fsal_posixdb_status_t st; unsigned int count, i; st = fsal_posixdb_getChildren(p_conn, p_handle_parent, 0, &p_children, &count); if(FSAL_POSIXDB_IS_ERROR(st)) { fprintf(stderr, "Error (%i/%i) while getting children of %s\n", st.major, st.minor, basedir); return; } for(i = 0; i < count; i++) { printf("%llu %s/%s\n", (unsigned long long int)p_children[i].handle.data.info.inode, basedir, p_children[i].name.name); if(p_children[i].handle.data.info.ftype == FSAL_TYPE_DIR) { char basedir_new[FSAL_MAX_PATH_LEN]; memset( basedir_new, 0, FSAL_MAX_PATH_LEN ) ; strncpy(basedir_new, basedir, FSAL_MAX_PATH_LEN); strncat(basedir_new, "/", FSAL_MAX_PATH_LEN); strncat(basedir_new, p_children[i].name.name, FSAL_MAX_PATH_LEN); display_directory(p_conn, &(p_children[i].handle), basedir_new); } } gsh_free(p_children); }
/** * @brief Lock the line of the Handle table with inode & devid defined in p_info * * @param p_conn * Database connection * @param p_info * Information about the file * * @return ERR_FSAL_POSIXDB_NOERR if no error, * another error code else. */ fsal_posixdb_status_t fsal_posixdb_lockHandleForUpdate(fsal_posixdb_conn * p_conn, /* IN */ fsal_posixdb_fileinfo_t * p_info /* IN */ ) { result_handle_t res; fsal_posixdb_status_t st; char query[2048]; BeginTransaction(p_conn); snprintf(query, 2048, "SELECT handleid, handlets, nlink, ctime, ftype " "FROM Handle WHERE deviceid=%llu AND inode=%llu " "FOR UPDATE", (unsigned long long)p_info->devid, (unsigned long long)p_info->inode); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) { RollbackTransaction(p_conn); return st; } mysql_free_result(res); /* Do not end the transaction, because it will be closed by the next call to a posixdb function */ ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); }
fsal_posixdb_status_t fsal_posixdb_deleteHandle(fsal_posixdb_conn * p_conn, /* IN */ posixfsal_handle_t * p_parent_directory_handle /* IN */ ) { /* char handleid_str[MAX_HANDLEIDSTR_SIZE]; char handlets_str[MAX_HANDLETSSTR_SIZE]; const char *paramValues[2]; */ int found; result_handle_t res; fsal_posixdb_status_t st; char query[2048]; BeginTransaction(p_conn); LogFullDebug(COMPONENT_FSAL, "Deleting %llu.%u\n", p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts); snprintf(query, 2048, "SELECT Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Handle WHERE handleid=%llu AND handlets=%u FOR UPDATE", p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; found = mysql_num_rows(res); mysql_free_result(res); if(found) { /* entry found */ st = fsal_posixdb_recursiveDelete(p_conn, p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts, FSAL_TYPE_DIR); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; } return EndTransaction(p_conn); rollback: RollbackTransaction(p_conn); return st; }
fsal_posixdb_status_t fsal_posixdb_getParentDirHandle(fsal_posixdb_conn * p_conn, /* IN */ posixfsal_handle_t * p_object_handle, /* IN */ posixfsal_handle_t * p_parent_directory_handle /* OUT */ ) { fsal_posixdb_status_t st; MYSQL_ROW row; result_handle_t res; char query[2048]; /* sanity check */ if(!p_conn || !p_parent_directory_handle || !p_object_handle) ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); /* no need to start a transaction, there is only one query */ snprintf(query, 2048, "SELECT Parent.name, Parent.handleidparent, Parent.handletsparent, " "Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Parent LEFT JOIN Handle ON Parent.handleidparent = Handle.handleid AND Parent.handletsparent=Handle.handlets " "WHERE Parent.handleid=%llu AND Parent.handlets=%u", p_object_handle->data.id, p_object_handle->data.ts); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) return st; /* entry not found */ if(mysql_num_rows(res) == 0) { mysql_free_result(res); ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); } row = mysql_fetch_row(res); if(row == NULL) { mysql_free_result(res); ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); } LogDebug(COMPONENT_FSAL, "lookupPathsExt"); p_parent_directory_handle->data.id = atoll(row[1]); p_parent_directory_handle->data.ts = atoi(row[2]); posixdb_internal_fillFileinfoFromStrValues(&(p_parent_directory_handle->data.info), row[3], row[4], row[5], row[6], row[7]); mysql_free_result(res); ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); }
void emptydb(fsal_posixdb_conn * p_conn) { fsal_posixdb_status_t st; st = fsal_posixdb_flush(p_conn); if(FSAL_POSIXDB_IS_ERROR(st)) { fprintf(stderr, "Error (%i/%i) while emptying the database\n", st.major, st.minor); } else { printf("Database entries have been successfully deleted\n"); } return; }
/** * @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_status_t POSIXFSAL_InitClientContext(fsal_op_context_t * thr_context) { posixfsal_op_context_t * p_thr_context = (posixfsal_op_context_t *) thr_context; fsal_posixdb_status_t st; /* sanity check */ if(!p_thr_context) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_InitClientContext); /* initialy set the export entry to none */ p_thr_context->export_context = NULL; st = fsal_posixdb_connect(&global_posixdb_params, &(p_thr_context->p_conn)); if(FSAL_POSIXDB_IS_ERROR(st)) { LogCrit(COMPONENT_FSAL, "CRITICAL ERROR: Worker could not connect to database !!!"); Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_InitClientContext); } else { LogEvent(COMPONENT_FSAL, "Worker successfuly connected to database"); } /* sets the credential time */ /* p_thr_context->credential.last_update = time( NULL );*/ /* traces: prints p_credential structure */ /* LogDebug(COMPONENT_FSAL, "credential created:"); LogDebug(COMPONENT_FSAL, "\tuid = %d, gid = %d", p_thr_context->credential.hpss_usercred.SecPWent.Uid, p_thr_context->credential.hpss_usercred.SecPWent.Gid); LogDebug(COMPONENT_FSAL, "\tName = %s", p_thr_context->credential.hpss_usercred.SecPWent.Name); for ( i=0; i< p_thr_context->credential.hpss_usercred.NumGroups; i++ ) LogDebug(COMPONENT_FSAL, "\tAlt grp: %d", p_thr_context->credential.hpss_usercred.AltGroups[i] ); */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_InitClientContext); }
void find(fsal_posixdb_conn * p_conn) { posixfsal_handle_t handle_root; fsal_posixdb_status_t st; st = fsal_posixdb_getInfoFromName(p_conn, NULL, /* parent handle */ NULL, /* filename */ NULL, /* path */ &handle_root); if(FSAL_POSIXDB_IS_NOENT(st)) { fputs("Error : Root handle not found. Is the database empty ?", stderr); return; } else if(FSAL_POSIXDB_IS_ERROR(st)) { fprintf(stderr, "Error (%i/%i) while getting root handle\n", st.major, st.minor); return; } display_directory(p_conn, &handle_root, ""); return; }
fsal_posixdb_status_t fsal_posixdb_recursiveDelete(fsal_posixdb_conn * p_conn, char *handleid_str, char *handlets_str, fsal_nodetype_t ftype) { PGresult *p_res; fsal_posixdb_status_t st; fsal_nodetype_t ftype_tmp; unsigned int i; unsigned int i_max; const char *paramValues[2]; /* Sanity check */ if(!p_conn || !handleid_str || !handlets_str) { ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); } if(ftype == FSAL_TYPE_DIR) { /* We find all the children of the directory in order to delete them, and then we delete the current handle */ paramValues[0] = handleid_str; paramValues[1] = handlets_str; p_res = PQexecPrepared(p_conn, "lookupChildrenFU", 2, paramValues, NULL, NULL, 0); CheckResult(p_res); i_max = (unsigned int)PQntuples(p_res); for(i = 0; i < i_max; i++) { ftype_tmp = (fsal_nodetype_t) atoi(PQgetvalue(p_res, i, 2)); if(ftype_tmp == FSAL_TYPE_DIR) { st = fsal_posixdb_recursiveDelete(p_conn, PQgetvalue(p_res, i, 0), PQgetvalue(p_res, i, 1), ftype_tmp); } else { st = fsal_posixdb_deleteParent(p_conn, PQgetvalue(p_res, i, 0), /* handleidparent */ PQgetvalue(p_res, i, 1), /* handletsparent */ handleid_str, handlets_str, PQgetvalue(p_res, i, 3), /* filename */ atoi(PQgetvalue(p_res, i, 4)) /* nlink */ ); } if(FSAL_POSIXDB_IS_ERROR(st)) { PQclear(p_res); return st; } } PQclear(p_res); } /* Delete the Handle */ /* All Parent entries having this handle will be deleted thanks to foreign keys */ paramValues[0] = handleid_str; paramValues[1] = handlets_str; /* invalidate name cache */ fsal_posixdb_InvalidateCache(); p_res = PQexecPrepared(p_conn, "deleteHandle", 2, paramValues, NULL, NULL, 0); CheckCommand(p_res); ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); }
fsal_posixdb_status_t fsal_posixdb_getInfoFromHandle(fsal_posixdb_conn * p_conn, /* IN */ posixfsal_handle_t * p_object_handle, /* IN/OUT */ fsal_path_t * p_paths, /* OUT */ int paths_size, /* IN */ int *p_count /* OUT */ ) { fsal_posixdb_status_t st; result_handle_t res; MYSQL_ROW row; posixfsal_handle_t parent_directory_handle; int i_path; int toomanypaths = 0; char query[2048]; /* sanity check */ if(!p_conn || !p_object_handle || ((!p_paths || !p_count) && paths_size > 0)) { ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); } LogFullDebug(COMPONENT_FSAL, "OBJECT_ID=%lli\n", p_object_handle->data.id); BeginTransaction(p_conn); /* lookup for the handle of the file */ if(!fsal_posixdb_GetInodeCache(p_object_handle)) { snprintf(query, 2048, "SELECT Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Handle WHERE handleid=%llu AND handlets=%u", p_object_handle->data.id, p_object_handle->data.ts); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; /* p_res contains : Handle.deviceId, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype */ LogDebug(COMPONENT_FSAL, "lookupHandle(%llu,%u)", p_object_handle->data.id, (unsigned int)p_object_handle->data.ts); if((mysql_num_rows(res) != 1) || ((row = mysql_fetch_row(res)) == NULL)) { LogDebug(COMPONENT_FSAL, "lookupHandle=%d entries", mysql_num_rows(res)); mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); } posixdb_internal_fillFileinfoFromStrValues(&(p_object_handle->data.info), row[0], row[1], row[2], row[3], row[4]); mysql_free_result(res); /* update the inode */ fsal_posixdb_UpdateInodeCache(p_object_handle); } /* Build the paths of the object */ if(p_paths) { /* find all the paths to the object */ snprintf(query, 2048, "SELECT name, handleidparent, handletsparent " "FROM Parent WHERE handleid=%llu AND handlets=%u", p_object_handle->data.id, p_object_handle->data.ts); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; /* res contains name, handleidparent, handletsparent */ *p_count = mysql_num_rows(res); if(*p_count == 0) { mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_NOPATH, 0); } else if(*p_count > paths_size) { toomanypaths = 1; LogCrit(COMPONENT_FSAL, "Too many paths found for object %llu.%u: found=%u, max=%d", p_object_handle->data.id, p_object_handle->data.ts, *p_count, paths_size); *p_count = paths_size; } for(i_path = 0; i_path < *p_count; i_path++) { unsigned int tmp_len; row = mysql_fetch_row(res); if(row == NULL) { mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); } /* build the path of the parent directory */ parent_directory_handle.data.id = atoll(row[1]); parent_directory_handle.data.ts = atoi(row[2]); st = fsal_posixdb_buildOnePath(p_conn, &parent_directory_handle, &p_paths[i_path]); if(FSAL_POSIXDB_IS_ERROR(st)) goto free_res; tmp_len = p_paths[i_path].len; if((tmp_len > 0) && (p_paths[i_path].path[tmp_len - 1] == '/')) { /* then concatenate the name of the file */ /* but not concatenate '/' */ if((tmp_len + strlen(row[0]) >= FSAL_MAX_PATH_LEN)) { mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0); } strcpy(&p_paths[i_path].path[tmp_len], row[0]); p_paths[i_path].len += strlen(row[0]); } else { /* then concatenate the name of the file */ if((tmp_len + 1 + strlen(row[0]) >= FSAL_MAX_PATH_LEN)) { mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0); } p_paths[i_path].path[tmp_len] = '/'; strcpy(&p_paths[i_path].path[tmp_len + 1], row[0]); p_paths[i_path].len += 1 + strlen(row[0]); } /* insert the object into cache */ fsal_posixdb_CachePath(p_object_handle, &p_paths[i_path]); } mysql_free_result(res); } st = EndTransaction(p_conn); if(toomanypaths) ReturnCodeDB(ERR_FSAL_POSIXDB_TOOMANYPATHS, 0); else return st; free_res: mysql_free_result(res); rollback: RollbackTransaction(p_conn); return st; }
fsal_posixdb_status_t fsal_posixdb_getInfoFromName(fsal_posixdb_conn * p_conn, /* IN */ posixfsal_handle_t * p_parent_directory_handle, /* IN/OUT */ fsal_name_t * p_objectname, /* IN */ fsal_path_t * p_path, /* OUT */ posixfsal_handle_t * p_handle /* OUT */ ) { fsal_posixdb_status_t st; char query[2048]; result_handle_t res; MYSQL_ROW row; /* sanity check */ if(!p_conn || !p_handle) { ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); } LogFullDebug(COMPONENT_FSAL, "object_name='%s'\n", p_objectname->name ? p_objectname->name : "/"); BeginTransaction(p_conn); /* lookup for the handle of the file */ if(p_parent_directory_handle && p_parent_directory_handle->data.id) { snprintf(query, 2048, "SELECT Parent.handleid, Parent.handlets, Handle.deviceid, " "Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid AND Parent.handlets=Handle.handlets " "WHERE handleidparent=%llu AND handletsparent=%u AND name='%s'", p_parent_directory_handle->data.id, p_parent_directory_handle->data.ts, p_objectname->name); st = db_exec_sql(p_conn, query, &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; } else { /* get root handle: */ st = db_exec_sql(p_conn, "SELECT Parent.handleid, Parent.handlets, Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid AND Parent.handlets=Handle.handlets " "WHERE Parent.handleidparent=Parent.handleid AND Parent.handletsparent=Parent.handlets", &res); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; } /* res contains : Parent.handleid, Parent.handlets, Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype */ /* entry not found */ if((mysql_num_rows(res) != 1) || ((row = mysql_fetch_row(res)) == NULL)) { mysql_free_result(res); RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); } p_handle->data.id = atoll(row[0]); p_handle->data.ts = atoi(row[1]); posixdb_internal_fillFileinfoFromStrValues(&(p_handle->data.info), row[2], row[3], /* devid, inode */ row[4], /* nlink */ row[5], /* ctime */ row[6]); /* ftype */ mysql_free_result(res); /* Build the path of the object */ if(p_path && p_objectname) { /* build the path of the Parent */ st = fsal_posixdb_buildOnePath(p_conn, p_parent_directory_handle, p_path); if(FSAL_POSIXDB_IS_ERROR(st)) goto rollback; /* then concatenate the filename */ if(!(p_path->len + 1 + p_objectname->len < FSAL_MAX_PATH_LEN)) { RollbackTransaction(p_conn); ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0); } p_path->path[p_path->len] = '/'; strcpy(&p_path->path[p_path->len + 1], p_objectname->name); p_path->len += 1 + p_objectname->len; /* add the the path to cache */ fsal_posixdb_CachePath(p_handle, p_path); } else { /* update handle if it was in cache */ fsal_posixdb_UpdateInodeCache(p_handle); } return EndTransaction(p_conn); rollback: RollbackTransaction(p_conn); return st; }
/** * FSAL_opendir : * Opens a directory for reading its content. * * \param dir_handle (input) * the handle of the directory to be opened. * \param cred (input) * Permission context for the operation (user,...). * \param dir_descriptor (output) * pointer to an allocated structure that will receive * directory stream informations, on successfull completion. * \param dir_attributes (optional output) * On successfull completion,the structure pointed * by dir_attributes receives the new directory attributes. * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t POSIXFSAL_opendir(fsal_handle_t * dir_handle, /* IN */ fsal_op_context_t * context, /* IN */ fsal_dir_t * dir_descriptor, /* OUT */ fsal_attrib_list_t * p_dir_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * p_dir_handle = (posixfsal_handle_t *) dir_handle; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; posixfsal_dir_t * p_dir_descriptor = (posixfsal_dir_t *) dir_descriptor; int rc, errsv; fsal_status_t status; fsal_path_t fsalpath; struct stat buffstat; /* sanity checks * note : dir_attributes is optionnal. */ if(!p_dir_handle || !p_context || !p_dir_descriptor) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); /* get the path of the directory */ status = fsal_internal_getPathFromHandle(p_context, p_dir_handle, 1, &fsalpath, &buffstat); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_opendir); /* Test access rights for this directory */ status = fsal_internal_testAccess(p_context, FSAL_R_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_opendir); /* if everything is OK, fills the dir_desc structure : */ TakeTokenFSCall(); p_dir_descriptor->p_dir = opendir(fsalpath.path); ReleaseTokenFSCall(); if(!p_dir_descriptor->p_dir) Return(posix2fsal_error(errno), errno, INDEX_FSAL_opendir); memcpy(&(p_dir_descriptor->context), p_context, sizeof(posixfsal_op_context_t)); memcpy(&(p_dir_descriptor->path), &fsalpath, sizeof(fsal_path_t)); memcpy(&(p_dir_descriptor->handle), p_dir_handle, sizeof(posixfsal_handle_t)); #ifdef _USE_POSIXDB_READDIR_BLOCK p_dir_descriptor->p_dbentries = NULL; p_dir_descriptor->dbentries_count = 0; /* fill the p_dbentries list */ statusdb = fsal_posixdb_getChildren(p_dir_descriptor->context.p_conn, &(p_dir_descriptor->handle), FSAL_POSIXDB_MAXREADDIRBLOCKSIZE, &(p_dir_descriptor->p_dbentries), &(p_dir_descriptor->dbentries_count)); if(FSAL_POSIXDB_IS_ERROR(statusdb)) /* too many entries in the directory, or another error */ p_dir_descriptor->dbentries_count = -1; #endif if(p_dir_attributes) { TakeTokenFSCall(); rc = lstat(fsalpath.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) /* lstat failed */ goto attr_err; status = posix2fsal_attributes(&buffstat, p_dir_attributes); if(FSAL_IS_ERROR(status)) { attr_err: FSAL_CLEAR_MASK(p_dir_attributes->asked_attributes); FSAL_SET_MASK(p_dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); }
/** * 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); }
fsal_posixdb_status_t fsal_posixdb_add(fsal_posixdb_conn * p_conn, /* IN */ fsal_posixdb_fileinfo_t * p_object_info, /* IN */ posixfsal_handle_t * p_parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ posixfsal_handle_t * p_object_handle /* OUT */ ) { PGresult *p_res; char handleid_str[MAX_HANDLEIDSTR_SIZE]; char handlets_str[MAX_HANDLETSSTR_SIZE]; char handleidparent_str[MAX_HANDLEIDSTR_SIZE]; char handletsparent_str[MAX_HANDLETSSTR_SIZE]; char devid_str[MAX_DEVICEIDSTR_SIZE]; char inode_str[MAX_INODESTR_SIZE]; int found; const char *paramValues[6]; fsal_posixdb_status_t st; /******************* * 1/ sanity check * *******************/ /* parent_directory and filename are NULL only if it is the root directory */ if(!p_conn || !p_object_info || !p_object_handle || (p_filename && !p_parent_directory_handle) || (!p_filename && p_parent_directory_handle)) ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); CheckConn(p_conn); LogFullDebug(COMPONENT_FSAL, "adding entry with parentid=%llu, id=%"PRIu64", name=%s\n", p_parent_directory_handle ? p_parent_directory_handle->data.id : 0, p_object_info ? p_object_info->inode : 0, p_filename ? p_filename->name : "NULL"); BeginTransaction(p_conn, p_res); /********************************* * 2/ we check the parent handle * *********************************/ if(p_parent_directory_handle) { /* the root has no parent */ snprintf(handleidparent_str, MAX_HANDLEIDSTR_SIZE, "%llu", p_parent_directory_handle->data.id); snprintf(handletsparent_str, MAX_HANDLETSSTR_SIZE, "%i", p_parent_directory_handle->data.ts); paramValues[0] = handleidparent_str; paramValues[1] = handletsparent_str; p_res = PQexecPrepared(p_conn, "lookupHandle", 2, paramValues, NULL, NULL, 0); CheckResult(p_res); if(PQntuples(p_res) != 1) { /* parent entry not found */ RollbackTransaction(p_conn, p_res); ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); } PQclear(p_res); } /********************************************************** * 3/ Check if there is an existing Handle for the object * **********************************************************/ snprintf(devid_str, MAX_DEVICEIDSTR_SIZE, "%llu", (unsigned long long int)p_object_info->devid); snprintf(inode_str, MAX_INODESTR_SIZE, "%llu", (unsigned long long int)p_object_info->inode); paramValues[0] = devid_str; paramValues[1] = inode_str; p_res = PQexecPrepared(p_conn, "lookupHandleByInodeFU", 2, paramValues, NULL, NULL, 0); CheckResult(p_res); found = (PQntuples(p_res) == 1); if(found) { /* a Handle (that matches devid & inode) already exists */ /* fill 'info' with information about the handle in the database */ posixdb_internal_fillFileinfoFromStrValues(&(p_object_handle->data.info), NULL, NULL, PQgetvalue(p_res, 0, 2), /* nlink */ PQgetvalue(p_res, 0, 3), /* ctime */ PQgetvalue(p_res, 0, 4) /* ftype */ ); p_object_handle->data.info.inode = p_object_info->inode; p_object_handle->data.info.devid = p_object_info->devid; strncpy(handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); strncpy(handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); PQclear(p_res); p_object_handle->data.id = atoll(handleid_str); p_object_handle->data.ts = atoi(handlets_str); /* check the consistency of the handle */ if(fsal_posixdb_consistency_check(&(p_object_handle->data.info), p_object_info)) { /* consistency check failed */ /* p_object_handle has been filled in order to be able to fix the consistency later */ RollbackTransaction(p_conn, p_res); ReturnCodeDB(ERR_FSAL_POSIXDB_CONSISTENCY, 0); } /* update nlink & ctime if needed */ if(p_object_info->nlink != p_object_handle->data.info.nlink || p_object_info->ctime != p_object_handle->data.info.ctime) { char nlink_str[MAX_NLINKSTR_SIZE]; char ctime_str[MAX_CTIMESTR_SIZE]; snprintf(nlink_str, MAX_NLINKSTR_SIZE, "%i", p_object_info->nlink); snprintf(ctime_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ctime); paramValues[0] = handleid_str; paramValues[1] = handlets_str; paramValues[2] = nlink_str; paramValues[3] = ctime_str; p_object_handle->data.info = *p_object_info; p_res = PQexecPrepared(p_conn, "updateHandle", 4, paramValues, NULL, NULL, 0); CheckCommand(p_res); } fsal_posixdb_UpdateInodeCache(p_object_handle); } else { /* no handle found */ /* Handle does not exist, add a new Handle entry */ char nlink_str[MAX_NLINKSTR_SIZE]; char ctime_str[MAX_CTIMESTR_SIZE]; char ftype_str[MAX_FTYPESTR_SIZE]; PQclear(p_res); p_object_handle->data.ts = (int)time(NULL); p_object_handle->data.info = *p_object_info; snprintf(handlets_str, MAX_HANDLETSSTR_SIZE, "%i", p_object_handle->data.ts); snprintf(nlink_str, MAX_NLINKSTR_SIZE, "%i", p_object_info->nlink); snprintf(ctime_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ctime); snprintf(ftype_str, MAX_CTIMESTR_SIZE, "%i", (int)p_object_info->ftype); paramValues[0] = devid_str; paramValues[1] = inode_str; paramValues[2] = handlets_str; paramValues[3] = nlink_str; paramValues[4] = ctime_str; paramValues[5] = ftype_str; p_res = PQexecPrepared(p_conn, "insertHandle", 6, paramValues, NULL, NULL, 0); CheckCommand(p_res); PQclear(p_res); p_res = PQexecPrepared(p_conn, "lookupHandleByInodeFU", 2, paramValues, NULL, NULL, 0); CheckResult(p_res); strncpy(handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); strncpy(handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); p_object_handle->data.id = atoll(PQgetvalue(p_res, 0, 0)); PQclear(p_res); /* now, we have the handle id */ fsal_posixdb_UpdateInodeCache(p_object_handle); } /************************************************ * add (or update) an entry in the Parent table * ************************************************/ paramValues[0] = p_parent_directory_handle ? handleidparent_str : handleid_str; paramValues[1] = p_parent_directory_handle ? handletsparent_str : handlets_str; paramValues[2] = p_filename ? p_filename->name : ""; p_res = PQexecPrepared(p_conn, "lookupParent", 3, paramValues, NULL, NULL, 0); CheckResult(p_res); /* p-res contains handleid & handlets */ found = (PQntuples(p_res) == 1); paramValues[3] = handleid_str; paramValues[4] = handlets_str; if(found) { /* update the Parent entry if necessary (there entry exists with another handle) */ if((fsal_u64_t) atoll(PQgetvalue(p_res, 0, 0)) != p_object_handle->data.id || atoi(PQgetvalue(p_res, 0, 1)) != p_object_handle->data.ts) { /* steps : - check the nlink value of the Parent entry to be overwritten - if nlink = 1, then we can delete the handle. else we have to update it (nlink--) : that is done by fsal_posixdb_deleteParent - update the handle of the entry */ char bad_handleid_str[MAX_HANDLEIDSTR_SIZE]; char bad_handlets_str[MAX_HANDLETSSTR_SIZE]; int nlink; strncpy(bad_handleid_str, PQgetvalue(p_res, 0, 0), MAX_HANDLEIDSTR_SIZE); strncpy(bad_handlets_str, PQgetvalue(p_res, 0, 1), MAX_HANDLETSSTR_SIZE); PQclear(p_res); /* clear old res before a new query */ /* check the nlink value of the entry to be updated */ paramValues[0] = handleidparent_str; paramValues[1] = handletsparent_str; p_res = PQexecPrepared(p_conn, "lookupHandleFU", 2, paramValues, NULL, NULL, 0); CheckResult(p_res); found = (PQntuples(p_res) == 1); if(found) { /* we have retrieved the handle information of the bad entry */ nlink = atoi(PQgetvalue(p_res, 0, 4)); PQclear(p_res); /* clear old res before a new query */ /* a Parent entry already exists, we delete it */ st = fsal_posixdb_deleteParent(p_conn, bad_handleid_str, bad_handlets_str, p_parent_directory_handle ? handleidparent_str : handleid_str, p_parent_directory_handle ? handletsparent_str : handlets_str, p_filename ? p_filename->name : "", nlink); if(FSAL_POSIXDB_IS_ERROR(st)) { RollbackTransaction(p_conn, p_res); return st; } } else { /* the Handle line has been deleted */ PQclear(p_res); /* clear old res before a new query */ } /* the bad entry has been deleted. Now we had a new Parent entry */ goto add_new_parent_entry; } else { /* a Parent entry exists with our handle, nothing to do */ PQclear(p_res); } } else { /* add a Parent entry */ PQclear(p_res); add_new_parent_entry: paramValues[0] = p_parent_directory_handle ? handleidparent_str : handleid_str; paramValues[1] = p_parent_directory_handle ? handletsparent_str : handlets_str; paramValues[2] = p_filename ? p_filename->name : ""; paramValues[3] = handleid_str; paramValues[4] = handlets_str; p_res = PQexecPrepared(p_conn, "insertParent", 5, paramValues, NULL, NULL, 0); CheckCommand(p_res); PQclear(p_res); /* XXX : is it possible to have unique key violation ? */ } EndTransaction(p_conn, p_res); ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); }
int main(int argc, char **argv) { fsal_posixdb_conn_params_t dbparams; char exec_name[MAXPATHLEN]; char c, op = 0; fsal_posixdb_conn *p_conn; fsal_posixdb_status_t statusdb; char path[MAXPATHLEN]; int rc; char options[] = "h@H:P:L:D:K:"; char usage[] = "Usage: %s [-h][-H <host>][-P <port>][-L <login>][-D <dbname>][-K <passwd file>] operation operation_parameters\n" "\t[-h] display this help\n" "\t[-H <host>] Database host\n" "\t[-P <port>] Database port\n" "\t[-L <login>] Database login\n" "\t[-D <dbname>] Name of the database\n" "\t[-K <passwd file>] Path of the file where is stored the password\n" "------------- Default Values -------------\n" "host : localhost\n" "port : default DB port\n" "dbname : posixdb\n" "login : current unix user\n" "passwd file : default path ($PGPASSFILE)\n" "------------- Operations -----------------\n" "test_connection : try to connect to the database\n" "empty_database : Delete all entries in the database\n" "find : Print the entries of the database (as 'find' would do it)\n" "populate <path> : Add (recursively) the object in <path> into the database\n\n"; memset(&dbparams, 0, sizeof(fsal_posixdb_conn_params_t)); strcpy(dbparams.host, "localhost"); strcpy(dbparams.dbname, "posixdb"); /* What is the executable file's name */ if(*exec_name == '\0') strcpy((char *)exec_name, basename(argv[0])); /* now parsing options with getopt */ while((c = getopt(argc, argv, options)) != EOF) { switch (c) { case '@': /* A litlle backdoor to keep track of binary versions */ printf("%s compiled on %s at %s\n", exec_name, __DATE__, __TIME__); exit(0); break; case 'H': strncpy(dbparams.host, optarg, FSAL_MAX_DBHOST_NAME_LEN); break; case 'P': strncpy(dbparams.port, optarg, FSAL_MAX_DBPORT_STR_LEN); break; case 'L': strncpy(dbparams.login, optarg, FSAL_MAX_DB_LOGIN_LEN); break; case 'D': strncpy(dbparams.dbname, optarg, FSAL_MAX_DB_NAME_LEN); break; case 'K': strncpy(dbparams.passwdfile, optarg, PATH_MAX); break; default: /* display the help */ fprintf(stderr, usage, exec_name); exit(0); break; } } if(optind == argc) { fprintf(stderr, "No operation specified.\n"); fprintf(stderr, usage, exec_name); exit(0); } if(optind < argc) { if(!strcmp(argv[optind], "test_connection")) { op = OP_TESTCONN; } else if(!strcmp(argv[optind], "empty_database")) { op = OP_EMPTYDB; } else if(!strcmp(argv[optind], "find")) { op = OP_FIND; } else if(!strcmp(argv[optind], "populate")) { op = OP_POPULATE; optind++; if(optind < argc) { strncpy(path, argv[optind], MAXPATHLEN); } else { fputs("Operation 'populate' need a parameter", stderr); fprintf(stderr, usage, exec_name); exit(-1); } } else { fprintf(stderr, "Unknown operation : %s\n", argv[optind]); fprintf(stderr, usage, exec_name); exit(-1); } } /* Connecting to database */ if(*(dbparams.passwdfile) != '\0') { rc = setenv("PGPASSFILE", dbparams.passwdfile, 1); if(rc != 0) fputs("Could not set POSTGRESQL keytab path.", stderr); } fprintf(stderr, "Opening database connection to %s...\n", dbparams.host); statusdb = fsal_posixdb_connect(&dbparams, &p_conn); if(FSAL_POSIXDB_IS_ERROR(statusdb)) { fprintf(stderr, "Error %i. exiting.\n", statusdb.minor); exit(-1); } else { fprintf(stderr, "Connected.\n"); } /* Execute the operation */ switch (op) { case OP_TESTCONN: /* nothing to do */ break; case OP_EMPTYDB: emptydb(p_conn); break; case OP_FIND: find(p_conn); break; case OP_POPULATE: populatedb(p_conn, path); break; default: puts("Bad operation !!"); fprintf(stderr, usage, exec_name); } fsal_posixdb_disconnect(p_conn); exit(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); }
/** * @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); }