예제 #1
0
/**
 * @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;
    }
}
예제 #2
0
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;
}