/** * @brief Moves up or down one directory * @details Helper function of cmd_line_cd * Moves up or down one directory, specified by dname * @param dname Next directory in which to move */ void process_path_part(const char *dname, char *abs_path) { if (strcmp(dname, ".") == 0) { return; } else if (strcmp(dname, "..") == 0) { // Move up one directory move_up_directory(abs_path); return; } else { move_into_directory(dname, abs_path); return; } }
static int vt_next(sqlite3_vtab_cursor *cur) { vtab_cursor *p_cur = (vtab_cursor*)cur; vtab* p_vt = (vtab*)cur->pVtab; /** This is a rather involved function. It is the core of this virtual * table. This function recursively reads down into a directory. It * automatically decends into a directory when it finds one, and * automatically ascends out of it when it has read all of its entries. * The logic is as follows: * The p_cur->current_node (a filenode struct) points to the current file * entry (given by the APR handle p_cur->current_node->dirent) and its * associated directory (given by the APR handle * p_cur->current_node->dirent) * We attempt to read the next entry in p_cur->current_node->dir, filling * the p_cur->current_node->dirent. If we succeed, then we have either a * file or a directory. If we have a directory, then we descend into it. If * we have a file, we proceed as usual. In either case, the dirent entry * will consitute a row in the result set, as we have done as much as we * have to and can exit the function. Our only job is to get to the next * valid file or directory entry to return as the current row in the * rowset. * If there are no more entries in the current directory, then we * deallocate p_cur->current_node and proceed up one directory (given by * p_cur->current_node->parent). We thus set p_cur->current_node to * p_cur->current_node->parent, and start over again. */ read_next_entry: /** First, check for a special case where the top level directory is * actually a top-level file. In this case, we rely that * p_cur->current_node->dir == NULL (set by next_directory()). If this is * true, resort to next_directory(). */ if (p_cur->current_node->dir == NULL) { return next_directory(p_cur); } /* Read the next directory entry. */ /* Increment the current row count. */ p_cur->count += 1; struct filenode* d = p_cur->current_node; struct filenode* prev_d = d; reread_next_entry: /* Read the next entry in the directory (d->dir). Fills the d->dirent member. */ if ( apr_dir_read( &d->dirent, APR_FINFO_DIRENT|APR_FINFO_PROT|APR_FINFO_TYPE| APR_FINFO_NAME|APR_FINFO_SIZE, d->dir) != APR_SUCCESS ) { /** If we get here, the call failed. There are no more entries in * directory. */ /** If we are at the top level directory */ if (d->parent == NULL) { /** We are done with this directory. See if there is another * top-level directory to search. * * If there is not another directory, next_directory() will have set * eof=1. We are at the end of the result set. If there is another * directory to search, then it will load the next dirent for * us. Either way, we have nothing left to do here. */ return next_directory(p_cur); } else { /** There is a parent directory that we still have to search * through. Free this filenode and resume iterating through the * parent. */ d = move_up_directory(p_cur); /* Start over, reading the next entry from parent. */ goto read_next_entry; } } /* If the current dirent is a directory, then descend into it. */ if (d->dirent.filetype == APR_DIR) { /* Skip . and .. entries */ if (d->dirent.name != NULL) { if (strcmp(d->dirent.name, ".") == 0 || strcmp(d->dirent.name, "..") == 0) { goto read_next_entry; } } /* Create a new child directory node */ /* Combine the path and file names to get full path */ char path[1024]; sprintf(&path[0], "%s/%s", d->path, d->dirent.name); /* Allocate space for new filenode and initlialize members. */ d = malloc(sizeof(struct filenode)); d->path = strdup(path); d->parent = p_cur->current_node; /* See note ZERO-FILL DIRENT below. */ memset(&d->dirent, 0, sizeof(apr_finfo_t)); /* Set current pointer to it. */ p_cur->current_node = d; /* Clear the pool memory associated with the path string allocated above. */ apr_pool_clear(p_cur->tmp_pool); /* Open the directory */ if ((p_cur->status = apr_dir_open(&d->dir, d->path, p_cur->pool)) != APR_SUCCESS) { /* Problem. Couldn't open directory. */ fprintf( stderr, "Failed to open directory: %s\n", p_cur->current_node->path ); /* Set this to null to move_up_directory() doesn't try to * apr_close() it (->core dump) */ p_cur->current_node->dir = NULL; /* Skip to next entry */ deallocate_filenode(d); p_cur->current_node = d = prev_d; goto reread_next_entry; } /* Else we were able to open directory. Update the currnet dirent info ** to that of the opened directory. This is our next row in the result ** set. */ apr_stat( &d->dirent, d->path, APR_FINFO_DIRENT|APR_FINFO_TYPE|APR_FINFO_NAME, p_cur->pool ); } return SQLITE_OK; }