📄 locks.c
字号:
/* ### does this allocation have a proper lifetime? need to check */ /* ### can we use a buffer for this? */ /* size is TYPE + pathname + null */ key.dsize = strlen(pathname) + 2; key.dptr = apr_palloc(p, key.dsize); *key.dptr = DAV_TYPE_FNAME; memcpy(key.dptr + 1, pathname, key.dsize - 1); if (key.dptr[key.dsize - 2] == '/') key.dptr[--key.dsize - 1] = '\0'; return key;}/* * dav_generic_lock_expired: return 1 (true) if the given timeout is in the * past or present (the lock has expired), or 0 (false) if in the future * (the lock has not yet expired). */static int dav_generic_lock_expired(time_t expires){ return expires != DAV_TIMEOUT_INFINITE && time(NULL) >= expires;}/* * dav_generic_save_lock_record: Saves the lock information specified in the * direct and indirect lock lists about path into the lock database. * If direct and indirect == NULL, the key is removed. */static dav_error * dav_generic_save_lock_record(dav_lockdb *lockdb, apr_datum_t key, dav_lock_discovery *direct, dav_lock_indirect *indirect){ dav_error *err; apr_status_t status; apr_datum_t val = { 0 }; char *ptr; dav_lock_discovery *dp = direct; dav_lock_indirect *ip = indirect;#if DAV_DEBUG if (lockdb->ro) { return dav_new_error(lockdb->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "INTERNAL DESIGN ERROR: the lockdb was opened " "readonly, but an attempt to save locks was " "performed."); }#endif if ((err = dav_generic_really_open_lockdb(lockdb)) != NULL) { /* ### add a higher-level error? */ return err; } /* If nothing to save, delete key */ if (dp == NULL && ip == NULL) { /* don't fail if the key is not present */ /* ### but what about other errors? */ apr_dbm_delete(lockdb->info->db, key); return NULL; } while(dp) { val.dsize += dav_size_direct(dp); dp = dp->next; } while(ip) { val.dsize += dav_size_indirect(ip); ip = ip->next; } /* ### can this be apr_palloc() ? */ /* ### hmmm.... investigate the use of a buffer here */ ptr = val.dptr = apr_pcalloc(lockdb->info->pool, val.dsize); dp = direct; ip = indirect; while(dp) { /* Direct lock - lock_discovery struct follows */ *ptr++ = DAV_LOCK_DIRECT; memcpy(ptr, dp, sizeof(dp->f)); /* Fixed portion of struct */ ptr += sizeof(dp->f); memcpy(ptr, dp->locktoken, sizeof(*dp->locktoken)); ptr += sizeof(*dp->locktoken); if (dp->owner == NULL) { *ptr++ = '\0'; } else { memcpy(ptr, dp->owner, strlen(dp->owner) + 1); ptr += strlen(dp->owner) + 1; } if (dp->auth_user == NULL) { *ptr++ = '\0'; } else { memcpy(ptr, dp->auth_user, strlen(dp->auth_user) + 1); ptr += strlen(dp->auth_user) + 1; } dp = dp->next; } while(ip) { /* Indirect lock prefix */ *ptr++ = DAV_LOCK_INDIRECT; memcpy(ptr, ip->locktoken, sizeof(*ip->locktoken)); ptr += sizeof(*ip->locktoken); memcpy(ptr, &ip->timeout, sizeof(ip->timeout)); ptr += sizeof(ip->timeout); memcpy(ptr, &ip->key.dsize, sizeof(ip->key.dsize)); ptr += sizeof(ip->key.dsize); memcpy(ptr, ip->key.dptr, ip->key.dsize); ptr += ip->key.dsize; ip = ip->next; } if ((status = apr_dbm_store(lockdb->info->db, key, val)) != APR_SUCCESS) { /* ### more details? add an error_id? */ err = dav_generic_dbm_new_error(lockdb->info->db, lockdb->info->pool, status); return dav_push_error(lockdb->info->pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_SAVE_LOCK, "Could not save lock information.", err); } return NULL;}/* * dav_load_lock_record: Reads lock information about key from lock db; * creates linked lists of the direct and indirect locks. * * If add_method = DAV_APPEND_LIST, the result will be appended to the * head of the direct and indirect lists supplied. * * Passive lock removal: If lock has timed out, it will not be returned. * ### How much "logging" does RFC 2518 require? */static dav_error * dav_generic_load_lock_record(dav_lockdb *lockdb, apr_datum_t key, int add_method, dav_lock_discovery **direct, dav_lock_indirect **indirect){ apr_pool_t *p = lockdb->info->pool; dav_error *err; apr_status_t status; apr_size_t offset = 0; int need_save = DAV_FALSE; apr_datum_t val = { 0 }; dav_lock_discovery *dp; dav_lock_indirect *ip; if (add_method != DAV_APPEND_LIST) { *direct = NULL; *indirect = NULL; } if ((err = dav_generic_really_open_lockdb(lockdb)) != NULL) { /* ### add a higher-level error? */ return err; } /* * If we opened readonly and the db wasn't there, then there are no * locks for this resource. Just exit. */ if (lockdb->info->db == NULL) { return NULL; } if ((status = apr_dbm_fetch(lockdb->info->db, key, &val)) != APR_SUCCESS) { return dav_generic_dbm_new_error(lockdb->info->db, p, status); } if (!val.dsize) { return NULL; } while (offset < val.dsize) { switch (*(val.dptr + offset++)) { case DAV_LOCK_DIRECT: /* Create and fill a dav_lock_discovery structure */ dp = apr_pcalloc(p, sizeof(*dp)); /* Copy the dav_lock_discovery_fixed portion */ memcpy(dp, val.dptr + offset, sizeof(dp->f)); offset += sizeof(dp->f); /* Copy the lock token. */ dp->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*dp->locktoken)); offset += sizeof(*dp->locktoken); /* Do we have an owner field? */ if (*(val.dptr + offset) == '\0') { ++offset; } else { apr_size_t len = strlen(val.dptr + offset); dp->owner = apr_pstrmemdup(p, val.dptr + offset, len); offset += len + 1; } if (*(val.dptr + offset) == '\0') { ++offset; } else { apr_size_t len = strlen(val.dptr + offset); dp->auth_user = apr_pstrmemdup(p, val.dptr + offset, len); offset += len + 1; } if (!dav_generic_lock_expired(dp->f.timeout)) { dp->next = *direct; *direct = dp; } else { need_save = DAV_TRUE; } break; case DAV_LOCK_INDIRECT: /* Create and fill a dav_lock_indirect structure */ ip = apr_pcalloc(p, sizeof(*ip)); ip->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*ip->locktoken)); offset += sizeof(*ip->locktoken); memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout)); offset += sizeof(ip->timeout); /* length of datum */ ip->key.dsize = *((int *) (val.dptr + offset)); offset += sizeof(ip->key.dsize); ip->key.dptr = apr_pmemdup(p, val.dptr + offset, ip->key.dsize); offset += ip->key.dsize; if (!dav_generic_lock_expired(ip->timeout)) { ip->next = *indirect; *indirect = ip; } else { need_save = DAV_TRUE; } break; default: apr_dbm_freedatum(lockdb->info->db, val); /* ### should use a computed_desc and insert corrupt token data */ --offset; return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_CORRUPT_DB, apr_psprintf(p, "The lock database was found to " "be corrupt. offset %" APR_SIZE_T_FMT ", c=%02x", offset, val.dptr[offset])); } } apr_dbm_freedatum(lockdb->info->db, val); /* Clean up this record if we found expired locks */ /* * ### shouldn't do this if we've been opened READONLY. elide the * ### timed-out locks from the response, but don't save that info back */ if (need_save == DAV_TRUE) { return dav_generic_save_lock_record(lockdb, key, *direct, *indirect); } return NULL;}/* resolve <indirect>, returning <*direct> */static dav_error * dav_generic_resolve(dav_lockdb *lockdb, dav_lock_indirect *indirect, dav_lock_discovery **direct, dav_lock_discovery **ref_dp, dav_lock_indirect **ref_ip){ dav_error *err; dav_lock_discovery *dir; dav_lock_indirect *ind; if ((err = dav_generic_load_lock_record(lockdb, indirect->key, DAV_CREATE_LIST, &dir, &ind)) != NULL) { /* ### insert a higher-level description? */ return err; } if (ref_dp != NULL) { *ref_dp = dir; *ref_ip = ind; } for (; dir != NULL; dir = dir->next) { if (!dav_compare_locktoken(indirect->locktoken, dir->locktoken)) { *direct = dir; return NULL; } } /* No match found (but we should have found one!) */ /* ### use a different description and/or error ID? */ return dav_new_error(lockdb->info->pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_CORRUPT_DB, "The lock database was found to be corrupt. " "An indirect lock's direct lock could not " "be found.");}/* --------------------------------------------------------------- * * Property-related lock functions * *//* * dav_generic_get_supportedlock: Returns a static string for all * supportedlock properties. I think we save more returning a static string * than constructing it every time, though it might look cleaner. */static const char *dav_generic_get_supportedlock(const dav_resource *resource){ static const char supported[] = DEBUG_CR "<D:lockentry>" DEBUG_CR "<D:lockscope><D:exclusive/></D:lockscope>" DEBUG_CR "<D:locktype><D:write/></D:locktype>" DEBUG_CR "</D:lockentry>" DEBUG_CR "<D:lockentry>" DEBUG_CR "<D:lockscope><D:shared/></D:lockscope>" DEBUG_CR "<D:locktype><D:write/></D:locktype>" DEBUG_CR "</D:lockentry>" DEBUG_CR; return supported;}/* --------------------------------------------------------------- * * General lock functions * */static dav_error * dav_generic_remove_locknull_state(dav_lockdb *lockdb, const dav_resource *resource){ /* We don't need to do anything. */ return NULL;}static dav_error * dav_generic_create_lock(dav_lockdb *lockdb, const dav_resource *resource, dav_lock **lock){ apr_datum_t key; key = dav_generic_build_key(lockdb->info->pool, resource); *lock = dav_generic_alloc_lock(lockdb, key, NULL); (*lock)->is_locknull = !resource->exists; return NULL;}static dav_error * dav_generic_get_locks(dav_lockdb *lockdb, const dav_resource *resource, int calltype, dav_lock **locks){ apr_pool_t *p = lockdb->info->pool; apr_datum_t key; dav_error *err; dav_lock *lock = NULL; dav_lock *newlock; dav_lock_discovery *dp; dav_lock_indirect *ip;#if DAV_DEBUG if (calltype == DAV_GETLOCKS_COMPLETE) { return dav_new_error(lockdb->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0, "INTERNAL DESIGN ERROR: DAV_GETLOCKS_COMPLETE " "is not yet supported"); }#endif key = dav_generic_build_key(p, resource); if ((err = dav_generic_load_lock_record(lockdb, key, DAV_CREATE_LIST, &dp, &ip)) != NULL) { /* ### push a higher-level desc? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -