⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 repos.c

📁 Apache 2.0.63 is the current stable version of the 2.0 series, and is recommended over any previous
💻 C
📖 第 1 页 / 共 5 页
字号:
                break;
            }

            /* put the various information back */
            fsctx->path1.cur_len = save_path_len;
            fsctx->path2.cur_len = save_path2_len;
            fsctx->uri_buf.cur_len = save_uri_len;

            fsctx->res1.collection = 0;
            fsctx->res2.collection = 0;

            /* assert: res1.exists == 1 */
        }
    }

    /* ### check the return value of this? */
    apr_dir_close(dirp);

    if (err != NULL)
        return err;

    if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
        apr_size_t offset = 0;

        /* null terminate the directory name */
        fsctx->path1.buf[fsctx->path1.cur_len - 1] = '\0';

        /* Include any lock null resources found in this collection */
        fsctx->res1.collection = 1;
        if ((err = dav_fs_get_locknull_members(&fsctx->res1,
                                               &fsctx->locknull_buf)) != NULL) {
            /* ### maybe add a higher-level description? */
            return err;
        }

        /* put a slash back on the end of the directory */
        fsctx->path1.buf[fsctx->path1.cur_len - 1] = '/';

        /* these are all non-existant (files) */
        fsctx->res1.exists = 0;
        fsctx->res1.collection = 0;
        memset(&fsctx->info1.finfo, 0, sizeof(fsctx->info1.finfo));

        while (offset < fsctx->locknull_buf.cur_len) {
            apr_size_t len = strlen(fsctx->locknull_buf.buf + offset);
            dav_lock *locks = NULL;

            /*
            ** Append the locknull file to the paths and the URI. Note that
            ** we don't have to pad the URI for a slash since a locknull
            ** resource is not a collection.
            */
            dav_buffer_place_mem(pool, &fsctx->path1,
                                 fsctx->locknull_buf.buf + offset, len + 1, 0);
            dav_buffer_place_mem(pool, &fsctx->uri_buf,
                                 fsctx->locknull_buf.buf + offset, len + 1, 0);
            if (fsctx->path2.buf != NULL) {
                dav_buffer_place_mem(pool, &fsctx->path2,
                                     fsctx->locknull_buf.buf + offset,
                                     len + 1, 0);
            }

            /* set up the (internal) pathnames for the two resources */
            fsctx->info1.pathname = fsctx->path1.buf;
            fsctx->info2.pathname = fsctx->path2.buf;

            /* set up the URI for the current resource */
            fsctx->res1.uri = fsctx->uri_buf.buf;

            /*
            ** To prevent a PROPFIND showing an expired locknull
            ** resource, query the lock database to force removal
            ** of both the lock entry and .locknull, if necessary..
            ** Sure, the query in PROPFIND would do this.. after
            ** the locknull resource was already included in the 
            ** return.
            **
            ** NOTE: we assume the caller has opened the lock database
            **       if they have provided DAV_WALKTYPE_LOCKNULL.
            */
            /* ### we should also look into opening it read-only and
               ### eliding timed-out items from the walk, yet leaving
               ### them in the locknull database until somebody opens
               ### the thing writable.
               */
            /* ### probably ought to use has_locks. note the problem
               ### mentioned above, though... we would traverse this as
               ### a locknull, but then a PROPFIND would load the lock
               ### info, causing a timeout and the locks would not be
               ### reported. Therefore, a null resource would be returned
               ### in the PROPFIND.
               ###
               ### alternative: just load unresolved locks. any direct
               ### locks will be timed out (correct). any indirect will
               ### not (correct; consider if a parent timed out -- the
               ### timeout routines do not walk and remove indirects;
               ### even the resolve func would probably fail when it
               ### tried to find a timed-out direct lock).
            */
            if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
                                      &locks)) != NULL) {
                /* ### maybe add a higher-level description? */
                return err;
            }

            /* call the function for the specified dir + file */
            if (locks != NULL &&
                (err = (*params->func)(&fsctx->wres,
                                       DAV_CALLTYPE_LOCKNULL)) != NULL) {
                /* ### maybe add a higher-level description? */
                return err;
            }

            offset += len + 1;
        }

        /* reset the exists flag */
        fsctx->res1.exists = 1;
    }

    if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
        /* replace the dirs' trailing slashes with null terms */
        fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
        fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
        if (fsctx->path2.buf != NULL) {
            fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
        }

        /* this is a collection which exists */
        fsctx->res1.collection = 1;

        return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
    }

    return NULL;
}

static dav_error * dav_fs_internal_walk(const dav_walk_params *params,
                                        int depth, int is_move,
                                        const dav_resource *root_dst,
                                        dav_response **response)
{
    dav_fs_walker_context fsctx = { 0 };
    dav_error *err;
    dav_fs_copymove_walk_ctx cm_ctx = { 0 };

#if DAV_DEBUG
    if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
        && params->lockdb == NULL) {
        return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "DESIGN ERROR: walker called to walk locknull "
                             "resources, but a lockdb was not provided.");
    }
#endif

    fsctx.params = params;
    fsctx.wres.walk_ctx = params->walk_ctx;
    fsctx.wres.pool = params->pool;

    /* ### zero out versioned, working, baselined? */

    fsctx.res1 = *params->root;
    fsctx.res1.pool = params->pool;

    fsctx.res1.info = &fsctx.info1;
    fsctx.info1 = *params->root->info;

    /* the pathname is stored in the path1 buffer */
    dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
    fsctx.info1.pathname = fsctx.path1.buf;

    if (root_dst != NULL) {
        /* internal call from the COPY/MOVE code. set it up. */

        fsctx.wres.walk_ctx = &cm_ctx;
        cm_ctx.is_move = is_move;
        cm_ctx.res_dst = &fsctx.res2;
        cm_ctx.root = params->root;
        cm_ctx.pool = params->pool;

        fsctx.res2 = *root_dst;
        fsctx.res2.exists = 0;
        fsctx.res2.collection = 0;
        fsctx.res2.uri = NULL;          /* we don't track this */
        fsctx.res2.pool = params->pool;

        fsctx.res2.info = &fsctx.info2;
        fsctx.info2 = *root_dst->info;

        /* res2 does not exist -- clear its finfo structure */
        memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));

        /* the pathname is stored in the path2 buffer */
        dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
        fsctx.info2.pathname = fsctx.path2.buf;
    }

    /* prep the URI buffer */
    dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);

    /* if we have a directory, then ensure the URI has a trailing "/" */
    if (fsctx.res1.collection
        && fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {

        /* this will fall into the pad area */
        fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
        fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
    }

    /* the current resource's URI is stored in the uri_buf buffer */
    fsctx.res1.uri = fsctx.uri_buf.buf;

    /* point the callback's resource at our structure */
    fsctx.wres.resource = &fsctx.res1;

    /* always return the error, and any/all multistatus responses */
    err = dav_fs_walker(&fsctx, depth);
    *response = fsctx.wres.response;
    return err;
}

static dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
                               dav_response **response)
{
    /* always return the error, and any/all multistatus responses */
    return dav_fs_internal_walk(params, depth, 0, NULL, response);
}

/* dav_fs_etag:  Stolen from ap_make_etag.  Creates a strong etag
 *    for file path.
 * ### do we need to return weak tags sometimes?
 */
static const char *dav_fs_getetag(const dav_resource *resource)
{
    dav_resource_private *ctx = resource->info;

    if (!resource->exists) 
        return apr_pstrdup(ctx->pool, "");

    if (ctx->finfo.filetype != 0) {
        return apr_psprintf(ctx->pool, "\"%lx-%lx-%lx\"",
                           (unsigned long) ctx->finfo.inode,
                           (unsigned long) ctx->finfo.size,
                           (unsigned long) ctx->finfo.mtime);
    }

    return apr_psprintf(ctx->pool, "\"%lx\"", (unsigned long) ctx->finfo.mtime);
}

static const dav_hooks_repository dav_hooks_repository_fs =
{
    DEBUG_GET_HANDLER,   /* normally: special GET handling not required */
    dav_fs_get_resource,
    dav_fs_get_parent_resource,
    dav_fs_is_same_resource,
    dav_fs_is_parent_resource,
    dav_fs_open_stream,
    dav_fs_close_stream,
    dav_fs_write_stream,
    dav_fs_seek_stream,
#if DEBUG_GET_HANDLER
    dav_fs_set_headers,
    dav_fs_deliver,
#else
    NULL,
    NULL,
#endif
    dav_fs_create_collection,
    dav_fs_copy_resource,
    dav_fs_move_resource,
    dav_fs_remove_resource,
    dav_fs_walk,
    dav_fs_getetag,
};

static dav_prop_insert dav_fs_insert_prop(const dav_resource *resource,
                                          int propid, dav_prop_insert what,
                                          apr_text_header *phdr)
{
    const char *value;
    const char *s;
    apr_pool_t *p = resource->info->pool;
    const dav_liveprop_spec *info;
    int global_ns;

    /* an HTTP-date can be 29 chars plus a null term */
    /* a 64-bit size can be 20 chars plus a null term */
    char buf[DAV_TIMEBUF_SIZE];

    /*
    ** None of FS provider properties are defined if the resource does not
    ** exist. Just bail for this case.
    **
    ** Even though we state that the FS properties are not defined, the
    ** client cannot store dead values -- we deny that thru the is_writable
    ** hook function.
    */
    if (!resource->exists)
        return DAV_PROP_INSERT_NOTDEF;

    switch (propid) {
    case DAV_PROPID_creationdate:
        /*
        ** Closest thing to a creation date. since we don't actually
        ** perform the operations that would modify ctime (after we
        ** create the file), then we should be pretty safe here.
        */
        dav_format_time(DAV_STYLE_ISO8601,
                        resource->info->finfo.ctime,
                        buf);
        value = buf;
        break;

    case DAV_PROPID_getcontentlength:
        /* our property, but not defined on collection resources */
        if (resource->collection)
            return DAV_PROP_INSERT_NOTDEF;

        (void) sprintf(buf, "%" APR_OFF_T_FMT, resource->info->finfo.size);
        value = buf;
        break;

    case DAV_PROPID_getetag:
        value = dav_fs_getetag(resource);
        break;

    case DAV_PROPID_getlastmodified:
        dav_format_time(DAV_STYLE_RFC822,
                        resource->info->finfo.mtime,
                        buf);
        value = buf;
        break;

    case DAV_PROPID_FS_executable:
        /* our property, but not defined on collection resources */
        if (resource->collection)
            return DAV_PROP_INSERT_NOTDEF;

        /* our property, but not defined on this platform */
        if (!(resource->info->finfo.valid & APR_FINFO_UPROT))
            return DAV_PROP_INSERT_NOTDEF;

        /* the files are "ours" so we only need to check owner exec privs */
        if (resource->info->finfo.protection & APR_UEXECUTE)
            value = "T";
        else
            value = "F";
        break;

    default:
        /* ### what the heck was this property? */
        return DAV_PROP_INSERT_NOTDEF;
    }

    /* assert: value != NULL */

    /* get the information and global NS index for the property */
    global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);

    /* assert: info != NULL && info->name != NULL */

    /* DBG3("FS: inserting lp%d:%s  (local %d)", ns, scan->name, scan->ns); */

    if (what == DAV_PROP_INSERT_VALUE) {
        s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
                         global_ns, info->name, value, global_ns, info->name);
    }
    else if (what == DAV_PROP_INSERT_NAME) {
        s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
    }
    else {
        /* assert: what == DAV_PROP_INSERT_SUPPORTED */
        s = apr_psprintf(p,
                         "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -