static char *canonicalize_path_and_cache(const char *path, struct libmnt_cache *cache) { char *p = NULL; char *key = NULL; char *value = NULL; DBG(CACHE, ul_debugobj(cache, "canonicalize path %s", path)); p = canonicalize_path(path); if (p && cache) { value = p; key = strcmp(path, p) == 0 ? value : strdup(path); if (!key || !value) goto error; if (cache_add_entry(cache, key, value, MNT_CACHE_ISPATH)) goto error; } return p; error: if (value != key) free(value); free(key); return NULL; }
/* add tag to the cache, @devname has to be an allocated string */ static int cache_add_tag(struct libmnt_cache *cache, const char *tagname, const char *tagval, char *devname, int flag) { size_t tksz, vlsz; char *key; int rc; assert(cache); assert(devname); assert(tagname); assert(tagval); /* add into cache -- cache format for TAGs is * key = "TAG_NAME\0TAG_VALUE\0" * value = "/dev/foo" */ tksz = strlen(tagname); vlsz = strlen(tagval); key = malloc(tksz + vlsz + 2); if (!key) return -ENOMEM; memcpy(key, tagname, tksz + 1); /* include '\0' */ memcpy(key + tksz + 1, tagval, vlsz + 1); rc = cache_add_entry(cache, key, devname, flag | MNT_CACHE_ISTAG); if (!rc) return 0; free(key); return rc; }
static void cache_copy(void* data, void* dest, xmlChar* name) { schema_cache* This = (schema_cache*) dest; cache_entry* entry = (cache_entry*) data; if (xmlHashLookup(This->cache, name) == NULL) { cache_entry_add_ref(entry); cache_add_entry(This, name, entry); } }
/* This one adds all namespaces defined in document to a cache, without anything associated with uri obviously. Unfortunately namespace:: axis implementation in libxml2 differs from what we need, it uses additional node type to describe namespace definition attribute while in msxml it's expected to be a normal attribute - as a workaround document is queried at libxml2 level here. */ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); static const xmlChar query[] = "//*/namespace::*"; xmlXPathObjectPtr nodeset; xmlXPathContextPtr ctxt; This->read_only = 1; ctxt = xmlXPathNewContext(node->node->doc); nodeset = xmlXPathEvalExpression(query, ctxt); xmlXPathFreeContext(ctxt); if (nodeset) { int pos = 0, len = xmlXPathNodeSetGetLength(nodeset->nodesetval); if (len == 0) return S_OK; while (pos < len) { xmlNodePtr node = xmlXPathNodeSetItem(nodeset->nodesetval, pos); if (node->type == XML_NAMESPACE_DECL) { static const xmlChar defns[] = "http://www.w3.org/XML/1998/namespace"; xmlNsPtr ns = (xmlNsPtr)node; cache_entry *entry; /* filter out default uri */ if (xmlStrEqual(ns->href, defns)) { pos++; continue; } entry = heap_alloc(sizeof(cache_entry)); entry->type = CacheEntryType_NS; entry->ref = 1; entry->schema = NULL; entry->doc = NULL; cache_add_entry(This, ns->href, entry); } pos++; } xmlXPathFreeObject(nodeset); } return S_OK; }
/** * mnt_resolve_target: * @path: "native" path, a potential mount point * @cache: cache for results or NULL. * * Like mnt_resolve_path(), unless @cache is not NULL and * mnt_cache_set_targets(cache, mtab) was called: if @path is found in the * cached @mtab and the matching entry was provided by the kernel, assume that * @path is already canonicalized. By avoiding a call to realpath(2) on * known mount points, there is a lower risk of stepping on a stale mount * point, which can result in an application freeze. This is also faster in * general, as stat(2) on a mount point is slower than on a regular file. * * Returns: absolute path or NULL in case of error. The result has to be * deallocated by free() if @cache is NULL. */ char *mnt_resolve_target(const char *path, struct libmnt_cache *cache) { char *p = NULL; /*DBG(CACHE, ul_debugobj(cache, "resolving target %s", path));*/ if (!cache || !cache->mtab) return mnt_resolve_path(path, cache); p = (char *) cache_find_path(cache, path); if (p) return p; else { struct libmnt_iter itr; struct libmnt_fs *fs = NULL; mnt_reset_iter(&itr, MNT_ITER_BACKWARD); while (mnt_table_next_fs(cache->mtab, &itr, &fs) == 0) { if (!mnt_fs_is_kernel(fs) || mnt_fs_is_swaparea(fs) || !mnt_fs_streq_target(fs, path)) continue; p = strdup(path); if (!p) return NULL; /* ENOMEM */ if (cache_add_entry(cache, p, p, MNT_CACHE_ISPATH)) { free(p); return NULL; /* ENOMEM */ } break; } } if (!p) p = canonicalize_path_and_cache(path, cache); return p; }
/** * mnt_resolve_path: * @path: "native" path * @cache: cache for results or NULL * * Converts path: * - to the absolute path * - /dev/dm-N to /dev/mapper/name * * Returns: absolute path or NULL in case of error. The result has to be * deallocated by free() if @cache is NULL. */ char *mnt_resolve_path(const char *path, struct libmnt_cache *cache) { char *p = NULL; char *key = NULL; char *value = NULL; /*DBG(CACHE, mnt_debug_h(cache, "resolving path %s", path));*/ if (!path) return NULL; if (cache) p = (char *) cache_find_path(cache, path); if (!p) { p = canonicalize_path(path); if (p && cache) { value = p; key = strcmp(path, p) == 0 ? value : strdup(path); if (!key || !value) goto error; if (cache_add_entry(cache, key, value, MNT_CACHE_ISPATH)) goto error; } } return p; error: if (value != key) free(value); free(key); return NULL; }
static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri, VARIANT var) { schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); xmlChar* name = uri ? xmlchar_from_wchar(uri) : xmlchar_from_wchar(emptyW); TRACE("(%p)->(%s %s)\n", This, debugstr_w(uri), debugstr_variant(&var)); if (This->read_only) return E_FAIL; switch (V_VT(&var)) { case VT_NULL: { cache_remove_entry(This, name); } break; case VT_BSTR: { cache_entry* entry = cache_entry_from_url(var, name, This->version); if (entry) { cache_entry_add_ref(entry); } else { heap_free(name); return E_FAIL; } cache_add_entry(This, name, entry); } break; case VT_DISPATCH: { xmlDocPtr doc = NULL; cache_entry* entry; CacheEntryType type; IXMLDOMNode* domnode = NULL; IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLDOMNode, (void**)&domnode); if (domnode) doc = xmlNodePtr_from_domnode(domnode, XML_DOCUMENT_NODE)->doc; if (!doc) { IXMLDOMNode_Release(domnode); heap_free(name); return E_INVALIDARG; } type = cache_type_from_xmlDocPtr(doc); if (type == CacheEntryType_XSD) { entry = cache_entry_from_xsd_doc(doc, name, This->version); } else if (type == CacheEntryType_XDR) { entry = cache_entry_from_xdr_doc(doc, name, This->version); } else { WARN("invalid schema!\n"); entry = NULL; } IXMLDOMNode_Release(domnode); if (entry) { cache_entry_add_ref(entry); } else { heap_free(name); return E_FAIL; } cache_add_entry(This, name, entry); } break; default: { heap_free(name); return E_INVALIDARG; } } heap_free(name); return S_OK; }