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

📄 util_lock.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. The end-user documentation included with the redistribution, *    if any, must include the following acknowledgment: *       "This product includes software developed by the *        Apache Software Foundation (http://www.apache.org/)." *    Alternately, this acknowledgment may appear in the software itself, *    if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", *    nor may "Apache" appear in their name, without prior written *    permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation.  For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. *//*** DAV repository-independent lock functions*/#include "apr.h"#include "apr_strings.h"#if APR_HAVE_STDIO_H#include <stdio.h>              /* for sprintf() */#endif#include "mod_dav.h"#include "http_log.h"#include "http_config.h"#include "http_protocol.h"#include "http_core.h"/* ---------------------------------------------------------------**** Property-related lock functions***//*** dav_lock_get_activelock:  Returns a <lockdiscovery> containing**    an activelock element for every item in the lock_discovery tree*/const char *dav_lock_get_activelock(request_rec *r, dav_lock *lock,				    dav_buffer *pbuf){    dav_lock *lock_scan;    const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);    int count = 0;    dav_buffer work_buf = { 0 };    apr_pool_t *p = r->pool;    /* If no locks or no lock provider, there are no locks */    if (lock == NULL || hooks == NULL) {	/*	** Since resourcediscovery is defined with (activelock)*, 	** <D:activelock/> shouldn't be necessary for an empty lock.	*/	return "";    }    /*    ** Note: it could be interesting to sum the lengths of the owners    **       and locktokens during this loop. However, the buffer    **       mechanism provides some rough padding so that we don't    **       really need to have an exact size. Further, constructing    **       locktoken strings could be relatively expensive.    */    for (lock_scan = lock; lock_scan != NULL; lock_scan = lock_scan->next)	count++;    /* if a buffer was not provided, then use an internal buffer */    if (pbuf == NULL)	pbuf = &work_buf;    /* reset the length before we start appending stuff */    pbuf->cur_len = 0;    /* prep the buffer with a "good" size */    dav_check_bufsize(p, pbuf, count * 300);    for (; lock != NULL; lock = lock->next) {	char tmp[100];#if DAV_DEBUG	if (lock->rectype == DAV_LOCKREC_INDIRECT_PARTIAL) {	    /* ### crap. design error */	    dav_buffer_append(p, pbuf,			      "DESIGN ERROR: attempted to product an "			      "activelock element from a partial, indirect "			      "lock record. Creating an XML parsing error "			      "to ease detection of this situation: <");	}#endif	dav_buffer_append(p, pbuf, "<D:activelock>" DEBUG_CR "<D:locktype>");	switch (lock->type) {	case DAV_LOCKTYPE_WRITE:	    dav_buffer_append(p, pbuf, "<D:write/>");	    break;	default:	    /* ### internal error. log something? */	    break;	}	dav_buffer_append(p, pbuf, "</D:locktype>" DEBUG_CR "<D:lockscope>");	switch (lock->scope) {	case DAV_LOCKSCOPE_EXCLUSIVE:	    dav_buffer_append(p, pbuf, "<D:exclusive/>");	    break;	case DAV_LOCKSCOPE_SHARED:	    dav_buffer_append(p, pbuf, "<D:shared/>");	    break;	default:	    /* ### internal error. log something? */	    break;	}	dav_buffer_append(p, pbuf, "</D:lockscope>" DEBUG_CR);	sprintf(tmp, "<D:depth>%s</D:depth>" DEBUG_CR,		lock->depth == DAV_INFINITY ? "infinity" : "0");	dav_buffer_append(p, pbuf, tmp);	if (lock->owner) {	    /*	    ** This contains a complete, self-contained <DAV:owner> element,	    ** with namespace declarations and xml:lang handling. Just drop	    ** it in.	    */	    dav_buffer_append(p, pbuf, lock->owner);	}			dav_buffer_append(p, pbuf, "<D:timeout>");	if (lock->timeout == DAV_TIMEOUT_INFINITE) {	    dav_buffer_append(p, pbuf, "Infinite");	}	else {	    time_t now = time(NULL);	    sprintf(tmp, "Second-%lu", lock->timeout - now);	    dav_buffer_append(p, pbuf, tmp);	}	dav_buffer_append(p, pbuf,			  "</D:timeout>" DEBUG_CR			  "<D:locktoken>" DEBUG_CR			  "<D:href>");	dav_buffer_append(p, pbuf,			  (*hooks->format_locktoken)(p, lock->locktoken));	dav_buffer_append(p, pbuf,			  "</D:href>" DEBUG_CR			  "</D:locktoken>" DEBUG_CR			  "</D:activelock>" DEBUG_CR);    }    return pbuf->buf;}/*** dav_lock_parse_lockinfo:  Validates the given xml_doc to contain a**    lockinfo XML element, then populates a dav_lock structure**    with its contents.*/dav_error * dav_lock_parse_lockinfo(request_rec *r,				    const dav_resource *resource,				    dav_lockdb *lockdb,				    const ap_xml_doc *doc,				    dav_lock **lock_request){    apr_pool_t *p = r->pool;    dav_error *err;    ap_xml_elem *child;    dav_lock *lock;    if (!dav_validate_root(doc, "lockinfo")) {	return dav_new_error(p, HTTP_BAD_REQUEST, 0,			     "The request body contains an unexpected "			     "XML root element.");    }    if ((err = (*lockdb->hooks->create_lock)(lockdb, resource,                                             &lock)) != NULL) {	return dav_push_error(p, err->status, 0,			      "Could not parse the lockinfo due to an "			      "internal problem creating a lock structure.",			      err);    }    lock->depth = dav_get_depth(r, DAV_INFINITY);    if (lock->depth == -1) {	return dav_new_error(p, HTTP_BAD_REQUEST, 0,			     "An invalid Depth header was specified.");    }    lock->timeout = dav_get_timeout(r);    /* Parse elements in the XML body */    for (child = doc->root->first_child; child; child = child->next) {	if (strcmp(child->name, "locktype") == 0	    && child->first_child	    && lock->type == DAV_LOCKTYPE_UNKNOWN) {	    if (strcmp(child->first_child->name, "write") == 0) {		lock->type = DAV_LOCKTYPE_WRITE;		continue;	    }	}	if (strcmp(child->name, "lockscope") == 0	    && child->first_child	    && lock->scope == DAV_LOCKSCOPE_UNKNOWN) {	    if (strcmp(child->first_child->name, "exclusive") == 0)		lock->scope = DAV_LOCKSCOPE_EXCLUSIVE;	    else if (strcmp(child->first_child->name, "shared") == 0)		lock->scope = DAV_LOCKSCOPE_SHARED;	    if (lock->scope != DAV_LOCKSCOPE_UNKNOWN)		continue;	}	if (strcmp(child->name, "owner") == 0 && lock->owner == NULL) {	    const char *text;	    /* quote all the values in the <DAV:owner> element */	    ap_xml_quote_elem(p, child);	    /*	    ** Store a full <DAV:owner> element with namespace definitions	    ** and an xml:lang definition, if applicable.	    */	    ap_xml_to_text(p, child, AP_XML_X2T_FULL_NS_LANG, doc->namespaces, 			   NULL, &text, NULL);	    lock->owner = text;	    continue;	}	return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0,			     apr_psprintf(p,					 "The server cannot satisfy the "					 "LOCK request due to an unknown XML "					 "element (\"%s\") within the "					 "DAV:lockinfo element.",					 child->name));    }    *lock_request = lock;    return NULL;}/* ---------------------------------------------------------------**** General lock functions***//* dav_lock_walker:  Walker callback function to record indirect locks */static dav_error * dav_lock_walker(dav_walk_resource *wres, int calltype){    dav_walker_ctx *ctx = wres->walk_ctx;    dav_error *err;    /* We don't want to set indirects on the target */    if ((*wres->resource->hooks->is_same_resource)(wres->resource,                                                   ctx->w.root))	return NULL;    if ((err = (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,                                                     wres->resource, 1,                                                     ctx->lock)) != NULL) {	if (ap_is_HTTP_SERVER_ERROR(err->status)) {	    /* ### add a higher-level description? */	    return err;	}	/* add to the multistatus response */	dav_add_response(wres, err->status, NULL);	/*	** ### actually, this is probably wrong: we want to fail the whole	** ### LOCK process if something goes bad. maybe the caller should	** ### do a dav_unlock() (e.g. a rollback) if any errors occurred.	*/    }    return NULL;}/*** dav_add_lock:  Add a direct lock for resource, and indirect locks for**    all children, bounded by depth.**    ### assume request only contains one lock*/dav_error * dav_add_lock(request_rec *r, const dav_resource *resource,			 dav_lockdb *lockdb, dav_lock *lock,			 dav_response **response){    dav_error *err;    int depth = lock->depth;    *response = NULL;    /* Requested lock can be:     *   Depth: 0   for null resource, existing resource, or existing collection     *   Depth: Inf for existing collection     */    /*    ** 2518 9.2 says to ignore depth if target is not a collection (it has    **   no internal children); pretend the client gave the correct depth.    */    if (!resource->collection) {	depth = 0;    }    /* In all cases, first add direct entry in lockdb */    /*    ** Append the new (direct) lock to the resource's existing locks.    **    ** Note: this also handles locknull resources    */    if ((err = (*lockdb->hooks->append_locks)(lockdb, resource, 0,                                              lock)) != NULL) {	/* ### maybe add a higher-level description */	return err;    }    if (depth > 0) {	/* Walk existing collection and set indirect locks */        dav_walker_ctx ctx = { { 0 } };        dav_response *multi_status;	ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;	ctx.w.func = dav_lock_walker;        ctx.w.walk_ctx = &ctx;	ctx.w.pool = r->pool;        ctx.w.root = resource;	ctx.w.lockdb = lockdb;	ctx.r = r;	ctx.lock = lock;	err = (*resource->hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);	if (err != NULL) {	    /* implies a 5xx status code occurred. screw the multistatus */	    return err;	}	if (multi_status != NULL) {	    /* manufacture a 207 error for the multistatus response */	    *response = multi_status;	    return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,				 "Error(s) occurred on resources during the "				 "addition of a depth lock.");	}    }    return NULL;}/*** dav_lock_query:  Opens the lock database. Returns a linked list of**    dav_lock structures for all direct locks on path.*/DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,                                        const dav_resource *resource,                                       dav_lock **locks){    /* If no lock database, return empty result */    if (lockdb == NULL) {        *locks = NULL;        return NULL;    }    /* ### insert a higher-level description? */    return (*lockdb->hooks->get_locks)(lockdb, resource,				       DAV_GETLOCKS_RESOLVED,				       locks);}/* dav_unlock_walker:  Walker callback function to remove indirect locks */static dav_error * dav_unlock_walker(dav_walk_resource *wres, int calltype)

⌨️ 快捷键说明

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