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

📄 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 页
字号:
    }

    apr_file_close(inf);
    apr_file_close(outf);

    if (is_move && apr_file_remove(src, p) != APR_SUCCESS) {
        dav_error *err;
        int save_errno = errno;   /* save the errno that got us here */

        if (apr_file_remove(dst, p) != APR_SUCCESS) {
            /* ### ACK. this creates an inconsistency. do more!? */

            /* ### use something besides 500? */
            /* Note that we use the latest errno */
            return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                                 "Could not remove source or destination "
                                 "file. Server is now in an inconsistent "
                                 "state.");
        }

        /* ### use something besides 500? */
        err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                            "Could not remove source file after move. "
                            "Destination was removed to ensure consistency.");
        err->save_errno = save_errno;
        return err;
    }

    return NULL;
}

/* copy/move a file from within a state dir to another state dir */
/* ### need more buffers to replace the pool argument */
static dav_error * dav_fs_copymove_state(
    int is_move,
    apr_pool_t * p,
    const char *src_dir, const char *src_file,
    const char *dst_dir, const char *dst_file,
    dav_buffer *pbuf)
{
    apr_finfo_t src_finfo;        /* finfo for source file */
    apr_finfo_t dst_state_finfo;        /* finfo for STATE directory */
    apr_status_t rv;
    const char *src;
    const char *dst;

    /* build the propset pathname for the source file */
    src = apr_pstrcat(p, src_dir, "/" DAV_FS_STATE_DIR "/", src_file, NULL);

    /* the source file doesn't exist */
    rv = apr_stat(&src_finfo, src, APR_FINFO_NORM, p);
    if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
        return NULL;
    }

    /* build the pathname for the destination state dir */
    dst = apr_pstrcat(p, dst_dir, "/" DAV_FS_STATE_DIR, NULL);

    /* ### do we need to deal with the umask? */

    /* ensure that it exists */
    rv = apr_dir_make(dst, APR_OS_DEFAULT, p);
    if (rv != APR_SUCCESS) {
        if (!APR_STATUS_IS_EEXIST(rv)) {
            /* ### use something besides 500? */
            return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                                 "Could not create internal state directory");
        }
    }

    /* get info about the state directory */
    rv = apr_stat(&dst_state_finfo, dst, APR_FINFO_NORM, p);
    if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) {
        /* Ack! Where'd it go? */
        /* ### use something besides 500? */
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "State directory disappeared");
    }

    /* The mkdir() may have failed because a *file* exists there already */
    if (dst_state_finfo.filetype != APR_DIR) {
        /* ### try to recover by deleting this file? (and mkdir again) */
        /* ### use something besides 500? */
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "State directory is actually a file");
    }

    /* append the target file to the state directory pathname */
    dst = apr_pstrcat(p, dst, "/", dst_file, NULL);

    /* copy/move the file now */
    if (is_move && src_finfo.device == dst_state_finfo.device) {
        /* simple rename is possible since it is on the same device */
        if (apr_file_rename(src, dst, p) != APR_SUCCESS) {
            /* ### use something besides 500? */
            return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                                 "Could not move state file.");
        }
    }
    else
    {
        /* gotta copy (and delete) */
        return dav_fs_copymove_file(is_move, p, src, dst, pbuf);
    }

    return NULL;
}

static dav_error *dav_fs_copymoveset(int is_move, apr_pool_t *p,
                                     const dav_resource *src,
                                     const dav_resource *dst,
                                     dav_buffer *pbuf)
{
    const char *src_dir;
    const char *src_file;
    const char *src_state1;
    const char *src_state2;
    const char *dst_dir;
    const char *dst_file;
    const char *dst_state1;
    const char *dst_state2;
    dav_error *err;

    /* Get directory and filename for resources */
    /* ### should test these result values... */
    (void) dav_fs_dir_file_name(src, &src_dir, &src_file);
    (void) dav_fs_dir_file_name(dst, &dst_dir, &dst_file);

    /* Get the corresponding state files for each resource */
    dav_dbm_get_statefiles(p, src_file, &src_state1, &src_state2);
    dav_dbm_get_statefiles(p, dst_file, &dst_state1, &dst_state2);
#if DAV_DEBUG
    if ((src_state2 != NULL && dst_state2 == NULL) ||
        (src_state2 == NULL && dst_state2 != NULL)) {
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "DESIGN ERROR: dav_dbm_get_statefiles() "
                             "returned inconsistent results.");
    }
#endif

    err = dav_fs_copymove_state(is_move, p,
                                src_dir, src_state1,
                                dst_dir, dst_state1,
                                pbuf);

    if (err == NULL && src_state2 != NULL) {
        err = dav_fs_copymove_state(is_move, p,
                                    src_dir, src_state2,
                                    dst_dir, dst_state2,
                                    pbuf);

        if (err != NULL) {
            /* ### CRAP. inconsistency. */
            /* ### should perform some cleanup at the target if we still
               ### have the original files */

            /* Change the error to reflect the bad server state. */
            err->status = HTTP_INTERNAL_SERVER_ERROR;
            err->desc =
                "Could not fully copy/move the properties. "
                "The server is now in an inconsistent state.";
        }
    }

    return err;
}

static dav_error *dav_fs_deleteset(apr_pool_t *p, const dav_resource *resource)
{
    const char *dirpath;
    const char *fname;
    const char *state1;
    const char *state2;
    const char *pathname;
    apr_status_t status;

    /* Get directory, filename, and state-file names for the resource */
    /* ### should test this result value... */
    (void) dav_fs_dir_file_name(resource, &dirpath, &fname);
    dav_dbm_get_statefiles(p, fname, &state1, &state2);

    /* build the propset pathname for the file */
    pathname = apr_pstrcat(p,
                          dirpath,
                          "/" DAV_FS_STATE_DIR "/",
                          state1,
                          NULL);

    /* note: we may get ENOENT if the state dir is not present */
    if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
        && !APR_STATUS_IS_ENOENT(status)) {
        return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                             "Could not remove properties.");
    }

    if (state2 != NULL) {
        /* build the propset pathname for the file */
        pathname = apr_pstrcat(p,
                              dirpath,
                              "/" DAV_FS_STATE_DIR "/",
                              state2,
                              NULL);

        if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
            && !APR_STATUS_IS_ENOENT(status)) {
            /* ### CRAP. only removed half. */
            return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
                                 "Could not fully remove properties. "
                                 "The server is now in an inconsistent "
                                 "state.");
        }
    }

    return NULL;
}

/* --------------------------------------------------------------------
**
** REPOSITORY HOOK FUNCTIONS
*/

static dav_error * dav_fs_get_resource(
    request_rec *r,
    const char *root_dir,
    const char *label,
    int use_checked_in,
    dav_resource **result_resource)
{
    dav_resource_private *ctx;
    dav_resource *resource;
    char *s;
    char *filename;
    apr_size_t len;

    /* ### optimize this into a single allocation! */

    /* Create private resource context descriptor */
    ctx = apr_pcalloc(r->pool, sizeof(*ctx));
    ctx->finfo = r->finfo;

    /* ### this should go away */
    ctx->pool = r->pool;

    /* Preserve case on OSes which fold canonical filenames */
#if 0
    /* ### not available in Apache 2.0 yet */
    filename = r->case_preserved_filename;
#else
    filename = r->filename;
#endif

    /*
    ** If there is anything in the path_info, then this indicates that the
    ** entire path was not used to specify the file/dir. We want to append
    ** it onto the filename so that we get a "valid" pathname for null
    ** resources.
    */
    s = apr_pstrcat(r->pool, filename, r->path_info, NULL);

    /* make sure the pathname does not have a trailing "/" */
    len = strlen(s);
    if (len > 1 && s[len - 1] == '/') {
        s[len - 1] = '\0';
    }
    ctx->pathname = s;

    /* Create resource descriptor */
    resource = apr_pcalloc(r->pool, sizeof(*resource));
    resource->type = DAV_RESOURCE_TYPE_REGULAR;
    resource->info = ctx;
    resource->hooks = &dav_hooks_repository_fs;
    resource->pool = r->pool;

    /* make sure the URI does not have a trailing "/" */
    len = strlen(r->uri);
    if (len > 1 && r->uri[len - 1] == '/') {
        s = apr_pstrdup(r->pool, r->uri);
        s[len - 1] = '\0';
        resource->uri = s;
    }
    else {
        resource->uri = r->uri;
    }

    if (r->finfo.filetype != 0) {
        resource->exists = 1;
        resource->collection = r->finfo.filetype == APR_DIR;

        /* unused info in the URL will indicate a null resource */

        if (r->path_info != NULL && *r->path_info != '\0') {
            if (resource->collection) {
                /* only a trailing "/" is allowed */
                if (*r->path_info != '/' || r->path_info[1] != '\0') {

                    /*
                    ** This URL/filename represents a locknull resource or
                    ** possibly a destination of a MOVE/COPY
                    */
                    resource->exists = 0;
                    resource->collection = 0;
                }
            }
            else
            {
                /*
                ** The base of the path refers to a file -- nothing should
                ** be in path_info. The resource is simply an error: it
                ** can't be a null or a locknull resource.
                */
                return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
                                     "The URL contains extraneous path "
                                     "components. The resource could not "
                                     "be identified.");
            }

            /* retain proper integrity across the structures */
            if (!resource->exists) {
                ctx->finfo.filetype = 0;
            }
        }
    }

    *result_resource = resource;
    return NULL;
}

static dav_error * dav_fs_get_parent_resource(const dav_resource *resource,
                                              dav_resource **result_parent)
{
    dav_resource_private *ctx = resource->info;
    dav_resource_private *parent_ctx;
    dav_resource *parent_resource;
    apr_status_t rv;
    char *dirpath;
    const char *testroot;
    const char *testpath;

    /* If we're at the root of the URL space, then there is no parent. */
    if (strcmp(resource->uri, "/") == 0) {
        *result_parent = NULL;
        return NULL;
    }

    /* If given resource is root, then there is no parent.
     * Unless we can retrieve the filepath root, this is
     * intendend to fail.  If we split the root and
     * no path info remains, then we also fail.
     */
    testpath = ctx->pathname;
    rv = apr_filepath_root(&testroot, &testpath, 0, ctx->pool);
    if ((rv != APR_SUCCESS && rv != APR_ERELATIVE) 
        || !testpath || !*testpath) {
        *result_parent = NULL;
        return NULL;
    }

    /* ### optimize this into a single allocation! */

    /* Create private resource context descriptor */
    parent_ctx = apr_pcalloc(ctx->pool, sizeof(*parent_ctx));

    /* ### this should go away */
    parent_ctx->pool = ctx->pool;

    dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
    if (strlen(dirpath) > 1 && dirpath[strlen(dirpath) - 1] == '/') 
        dirpath[strlen(dirpath) - 1] = '\0';
    parent_ctx->pathname = dirpath;

    parent_resource = apr_pcalloc(ctx->pool, sizeof(*parent_resource));
    parent_resource->info = parent_ctx;
    parent_resource->collection = 1;
    parent_resource->hooks = &dav_hooks_repository_fs;
    parent_resource->pool = resource->pool;

    if (resource->uri != NULL) {
        char *uri = ap_make_dirstr_parent(ctx->pool, resource->uri);

⌨️ 快捷键说明

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