void populatedb(fsal_posixdb_conn * p_conn, char *path) { int rc; fsal_posixdb_fileinfo_t info; fsal_name_t fsalname; posixfsal_handle_t handle, handle_parent; struct stat buffstat; char *begin, *end, backup; if(path[0] != '/') { fputs("Error : you should provide a complete path", stderr); return; } if(path[strlen(path) - 1] != '/') strcat(path, "/"); /* add the path (given in arguments) to the database */ rc = lstat("/", &buffstat); fsal_internal_posix2posixdb_fileinfo(&buffstat, &info); fsal_internal_posixdb_add_entry(p_conn, NULL, &info, NULL, &handle_parent); begin = end = path; while(*end != '\0') { while(*begin == '/') begin++; if(*begin == '\0') break; end = begin + 1; while(*end != '/' && *end != '\0') end++; backup = *end; *end = '\0'; rc = lstat(path, &buffstat); fsal_internal_posix2posixdb_fileinfo(&buffstat, &info); FSAL_str2name(begin, FSAL_MAX_NAME_LEN, &fsalname); fsal_internal_posixdb_add_entry(p_conn, &fsalname, &info, &handle_parent, &handle); memcpy(&handle_parent, &handle, sizeof(posixfsal_handle_t)); *end = backup; begin = end; } /* add files */ printf("Adding entries in %s... rc=%d ", path, rc); fflush(stdout); add_dir(p_conn, path, &handle_parent); puts("done"); }
void add_dir(fsal_posixdb_conn * p_conn, char *path, posixfsal_handle_t * p_dir_handle) { DIR *dirp; struct dirent *dp; struct dirent dpe; posixfsal_handle_t new_handle; struct stat buffstat; char path_temp[FSAL_MAX_PATH_LEN]; fsal_status_t st; fsal_posixdb_fileinfo_t info; fsal_name_t fsalname; if((dirp = opendir(path))) { while(!readdir_r(dirp, &dpe, &dp) && dp) { if(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if(!strcmp(dp->d_name, ".snapshot")) { fputs("(ignoring .snapshot)", stderr); continue; } strcpy(path_temp, path); strcat(path_temp, dp->d_name); lstat(path_temp, &buffstat); fsal_internal_posix2posixdb_fileinfo(&buffstat, &info); FSAL_str2name(dp->d_name, FSAL_MAX_NAME_LEN, &fsalname); st = fsal_internal_posixdb_add_entry(p_conn, &fsalname, &info, p_dir_handle, &new_handle); if(FSAL_IS_ERROR(st)) { fprintf(stderr, "[Error %i/%i]\n", st.major, st.minor); return; } if(S_ISDIR(buffstat.st_mode)) { strcat(path_temp, "/"); add_dir(p_conn, path_temp, &new_handle); } }; closedir(dirp); } }
/** * FSAL_create: * Create a regular file. * * \param parent_directory_handle (input): * Handle of the parent directory where the file is to be created. * \param p_filename (input): * Pointer to the name of the file to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the file to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param object_handle (output): * Pointer to the handle of the created file. * \param object_attributes (optional input/output): * The attributes of the created file. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occurred. */ fsal_status_t POSIXFSAL_create(fsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_filename, /* IN */ fsal_op_context_t * context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * p_parent_directory_handle = (posixfsal_handle_t *) parent_directory_handle; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; posixfsal_handle_t * p_object_handle = (posixfsal_handle_t *) p_object_handle; int rc, fd, errsv; int setgid_bit = 0; fsal_status_t status; fsal_path_t fsalpath; struct stat buffstat; fsal_posixdb_fileinfo_t info; mode_t unix_mode; /* sanity checks. * note : object_attributes is optional. */ if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_filename) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_create); /* convert fsal mode to unix mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; LogFullDebug(COMPONENT_FSAL, "Creation mode: 0%o", accessmode); /* build the destination path */ status = fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1, &fsalpath, &buffstat); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_create); /* Check the user can write in the directory, and check the setgid bit on the directory */ if(buffstat.st_mode & S_ISGID) setgid_bit = 1; status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_create); status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_filename); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_create); /* call to API */ TakeTokenFSCall(); /* create the file */ fd = open(fsalpath.path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, unix_mode); /* error if the file already exists */ errsv = errno; if(fd == -1) goto releaseToken; /* close the file descriptor */ rc = close(fd); errsv = errno; if(rc) goto releaseToken; /* stat the new file */ rc = lstat(fsalpath.path, &buffstat); errsv = errno; releaseToken: ReleaseTokenFSCall(); if(fd == -1 || rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); /* add the file to the database */ if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info))) Return(status.major, status.minor, INDEX_FSAL_create); if(FSAL_IS_ERROR (status = fsal_internal_posixdb_add_entry(p_context->p_conn, p_filename, &info, p_parent_directory_handle, p_object_handle))) Return(status.major, status.minor, INDEX_FSAL_create); /* the file has been created */ /* chown the file to the current user */ if(p_context->credential.user != geteuid()) { TakeTokenFSCall(); /* if the setgid_bit was set on the parent directory, * do not change the group of the created file, * because it's already the parentdir's group */ rc = lchown(fsalpath.path, p_context->credential.user, setgid_bit ? -1 : (int)p_context->credential.group); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_create); buffstat.st_uid = p_context->credential.user; buffstat.st_gid = p_context->credential.group; } /* add the file to the database */ if(p_object_attributes) { /* convert POSIX attributes to fsal attributes */ status = posix2fsal_attributes(&buffstat, p_object_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_create); }
/** * FSAL_mknode: * Create a special object in the filesystem. * Not supported upon HPSS. * * \return ERR_FSAL_NOTSUPP. */ fsal_status_t POSIXFSAL_mknode(fsal_handle_t * parentdir_hdl, /* IN */ fsal_name_t * p_node_name, /* IN */ fsal_op_context_t * context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_nodetype_t nodetype, /* IN */ fsal_dev_t * dev, /* IN */ fsal_handle_t * object_handle, /* OUT (handle to the created node) */ fsal_attrib_list_t * node_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * parentdir_handle = (posixfsal_handle_t *) parentdir_hdl; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; posixfsal_handle_t * p_object_handle = (posixfsal_handle_t *) object_handle; int rc, errsv; int setgid_bit = 0; struct stat buffstat; fsal_status_t status; fsal_path_t fsalpath; fsal_posixdb_fileinfo_t info; mode_t unix_mode = 0; dev_t unix_dev = 0; /* sanity checks. * note : link_attributes is optional. */ if(!parentdir_handle || !p_context || !p_node_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; switch (nodetype) { case FSAL_TYPE_BLK: if(!dev) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode |= S_IFBLK; unix_dev = (dev->major << 8) | (dev->minor & 0xFF); break; case FSAL_TYPE_CHR: if(!dev) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mknode); unix_mode |= S_IFCHR; unix_dev = (dev->major << 8) | (dev->minor & 0xFF); break; case FSAL_TYPE_SOCK: unix_mode |= S_IFSOCK; break; case FSAL_TYPE_FIFO: unix_mode |= S_IFIFO; break; default: LogMajor(COMPONENT_FSAL, "Invalid node type in FSAL_mknode: %d", nodetype); Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_mknode); } /* build the destination path */ status = fsal_internal_getPathFromHandle(p_context, parentdir_handle, 1, &fsalpath, &buffstat); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mknode); /* Check the user can write in the directory, and check weither the setgid bit on the directory */ if(buffstat.st_mode & S_ISGID) setgid_bit = 1; status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mknode); status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_node_name); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mknode); /* creates the node, then stats it */ TakeTokenFSCall(); rc = mknod(fsalpath.path, unix_mode, unix_dev); if(!rc) rc = lstat(fsalpath.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); /* add the object to the database */ if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info))) Return(status.major, status.minor, INDEX_FSAL_mknode); if(FSAL_IS_ERROR (status = fsal_internal_posixdb_add_entry(p_context->p_conn, p_node_name, &info, parentdir_handle, p_object_handle))) Return(status.major, status.minor, INDEX_FSAL_mknode); /* the node has been created */ /* chown the file to the current user/group */ if(p_context->credential.user != geteuid()) { TakeTokenFSCall(); /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ rc = lchown(fsalpath.path, p_context->credential.user, setgid_bit ? -1 : (int)p_context->credential.group); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mknode); buffstat.st_uid = p_context->credential.user; buffstat.st_gid = p_context->credential.group; } /* Fills the attributes if needed */ if(node_attributes) { status = posix2fsal_attributes(&buffstat, node_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(node_attributes->asked_attributes); FSAL_SET_MASK(node_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* Finished */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mknode); }
/** * FSAL_link: * Create a hardlink. * * \param target_handle (input): * Handle of the target object. * \param dir_handle (input): * Pointer to the directory handle where * the hardlink is to be created. * \param p_link_name (input): * Pointer to the name of the hardlink to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the directory to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param attributes (optionnal input/output): * The post_operation attributes of the linked object. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t POSIXFSAL_link(fsal_handle_t * target_handle, /* IN */ fsal_handle_t * dir_handle, /* IN */ fsal_name_t * p_link_name, /* IN */ fsal_op_context_t * context, /* IN */ fsal_attrib_list_t * p_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * p_target_handle = (posixfsal_handle_t *) target_handle; posixfsal_handle_t * p_dir_handle = (posixfsal_handle_t *) dir_handle; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; int rc, errsv; fsal_status_t status; fsal_path_t fsalpath_old, fsalpath_new; fsal_posixdb_fileinfo_t info; posixfsal_handle_t newhandle; struct stat buffstat, buffstat_dir; /* sanity checks. * note : attributes is optional. */ if(!p_target_handle || !p_dir_handle || !p_context || !p_link_name) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_link); /* Tests if hardlinking is allowed by configuration. */ if(!global_fs_info.link_support) Return(ERR_FSAL_NOTSUPP, 0, INDEX_FSAL_link); LogFullDebug(COMPONENT_FSAL, "linking %llu/%i to %llu.%i/%s \n", p_target_handle->data.id, p_target_handle->data.ts, p_dir_handle->data.id, p_dir_handle->data.ts, p_link_name->name); /* get the old path */ status = fsal_internal_getPathFromHandle(p_context, p_target_handle, 0, &fsalpath_old, &buffstat); if(FSAL_IS_ERROR(status)) { Return(status.major, status.minor, INDEX_FSAL_link); } /* build the destination path and check permissions on the directory */ status = fsal_internal_getPathFromHandle(p_context, p_dir_handle, 1, &fsalpath_new, &buffstat_dir); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_link); status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat_dir, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_link); status = fsal_internal_appendFSALNameToFSALPath(&fsalpath_new, p_link_name); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_link); /* Create the link on the filesystem */ TakeTokenFSCall(); rc = link(fsalpath_old.path, fsalpath_new.path); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_link); /* add the link in the database */ buffstat.st_nlink++; /* avoid to stat the new file */ status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_link); if(FSAL_IS_ERROR (status = fsal_internal_posixdb_add_entry(p_context->p_conn, p_link_name, &info, p_dir_handle, &newhandle))) Return(status.major, status.minor, INDEX_FSAL_link); /* optionnaly get attributes */ if(p_attributes) { TakeTokenFSCall(); rc = lstat(fsalpath_old.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) { status.major = posix2fsal_error(errsv); status.minor = errsv; } else { status = posix2fsal_attributes(&buffstat, p_attributes); } /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_attributes->asked_attributes); FSAL_SET_MASK(p_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_link); }
/** * FSAL_mkdir: * Create a directory. * * \param parent_directory_handle (input): * Handle of the parent directory where * the subdirectory is to be created. * \param p_dirname (input): * Pointer to the name of the directory to be created. * \param cred (input): * Authentication context for the operation (user,...). * \param accessmode (input): * Mode for the directory to be created. * (the umask defined into the FSAL configuration file * will be applied on it). * \param object_handle (output): * Pointer to the handle of the created directory. * \param object_attributes (optionnal input/output): * The attributes of the created directory. * As input, it defines the attributes that the caller * wants to retrieve (by positioning flags into this structure) * and the output is built considering this input * (it fills the structure according to the flags it contains). * May be NULL. * * \return Major error codes : * - ERR_FSAL_NO_ERROR (no error) * - Another error code if an error occured. */ fsal_status_t POSIXFSAL_mkdir(fsal_handle_t * parent_directory_handle, /* IN */ fsal_name_t * p_dirname, /* IN */ fsal_op_context_t * context, /* IN */ fsal_accessmode_t accessmode, /* IN */ fsal_handle_t * object_handle, /* OUT */ fsal_attrib_list_t * p_object_attributes /* [ IN/OUT ] */ ) { posixfsal_handle_t * p_parent_directory_handle = (posixfsal_handle_t *) parent_directory_handle; posixfsal_op_context_t * p_context = (posixfsal_op_context_t *) context; posixfsal_handle_t * p_object_handle = (posixfsal_handle_t *) object_handle; int rc, errsv; int setgid_bit = 0; struct stat buffstat; mode_t unix_mode; fsal_status_t status; fsal_path_t fsalpath; fsal_posixdb_fileinfo_t info; /* sanity checks. * note : object_attributes is optional. */ if(!p_parent_directory_handle || !p_context || !p_object_handle || !p_dirname) Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_mkdir); /* convert FSAL mode to HPSS mode. */ unix_mode = fsal2unix_mode(accessmode); /* Apply umask */ unix_mode = unix_mode & ~global_fs_info.umask; /* build the destination path */ status = fsal_internal_getPathFromHandle(p_context, p_parent_directory_handle, 1, &fsalpath, &buffstat); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mkdir); /* Check the user can write in the directory, and check the setgid bit on the directory */ if(buffstat.st_mode & S_ISGID) setgid_bit = 1; status = fsal_internal_testAccess(p_context, FSAL_W_OK | FSAL_X_OK, &buffstat, NULL); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mkdir); status = fsal_internal_appendFSALNameToFSALPath(&fsalpath, p_dirname); if(FSAL_IS_ERROR(status)) Return(status.major, status.minor, INDEX_FSAL_mkdir); /* creates the directory and stats it */ TakeTokenFSCall(); rc = mkdir(fsalpath.path, unix_mode); if(!rc) rc = lstat(fsalpath.path, &buffstat); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); /* add the directory to the database */ if(FSAL_IS_ERROR(status = fsal_internal_posix2posixdb_fileinfo(&buffstat, &info))) Return(status.major, status.minor, INDEX_FSAL_mkdir); if(FSAL_IS_ERROR (status = fsal_internal_posixdb_add_entry(p_context->p_conn, p_dirname, &info, p_parent_directory_handle, p_object_handle))) Return(status.major, status.minor, INDEX_FSAL_mkdir); /* the directory has been created */ /* chown the file to the current user/group */ if(p_context->credential.user != geteuid()) { TakeTokenFSCall(); /* if the setgid_bit was set on the parent directory, do not change the group of the created file, because it's already the parentdir's group */ rc = lchown(fsalpath.path, p_context->credential.user, setgid_bit ? -1 : (int)p_context->credential.group); errsv = errno; ReleaseTokenFSCall(); if(rc) Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_mkdir); buffstat.st_uid = p_context->credential.user; buffstat.st_gid = p_context->credential.group; } /* Fills the attributes if needed */ if(p_object_attributes) { status = posix2fsal_attributes(&buffstat, p_object_attributes); /* on error, we set a special bit in the mask. */ if(FSAL_IS_ERROR(status)) { FSAL_CLEAR_MASK(p_object_attributes->asked_attributes); FSAL_SET_MASK(p_object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); } } /* OK */ Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_mkdir); }
/** * 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); }
/** * 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); }