resource.c revision 9ace9065
105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrg 2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2705b261ecSmrg 2805b261ecSmrg All Rights Reserved 2905b261ecSmrg 3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3205b261ecSmrgprovided that the above copyright notice appear in all copies and that 3305b261ecSmrgboth that copyright notice and this permission notice appear in 3405b261ecSmrgsupporting documentation, and that the name of Digital not be 3505b261ecSmrgused in advertising or publicity pertaining to distribution of the 3605b261ecSmrgsoftware without specific, written prior permission. 3705b261ecSmrg 3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4405b261ecSmrgSOFTWARE. 4505b261ecSmrg 4605b261ecSmrg********************************************************/ 4705b261ecSmrg/* The panoramix components contained the following notice */ 4805b261ecSmrg/***************************************************************** 4905b261ecSmrg 5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 5105b261ecSmrg 5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal 5405b261ecSmrgin the Software without restriction, including without limitation the rights 5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5605b261ecSmrgcopies of the Software. 5705b261ecSmrg 5805b261ecSmrgThe above copyright notice and this permission notice shall be included in 5905b261ecSmrgall copies or substantial portions of the Software. 6005b261ecSmrg 6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6805b261ecSmrg 6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation 7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other 7105b261ecSmrgdealings in this Software without prior written authorization from Digital 7205b261ecSmrgEquipment Corporation. 7305b261ecSmrg 7405b261ecSmrg******************************************************************/ 7505b261ecSmrg/* XSERVER_DTRACE additions: 769ace9065Smrg * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved. 7705b261ecSmrg * 7805b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 796747b715Smrg * copy of this software and associated documentation files (the "Software"), 806747b715Smrg * to deal in the Software without restriction, including without limitation 816747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 826747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 836747b715Smrg * Software is furnished to do so, subject to the following conditions: 846747b715Smrg * 856747b715Smrg * The above copyright notice and this permission notice (including the next 866747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 876747b715Smrg * Software. 886747b715Smrg * 896747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 906747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 916747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 926747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 936747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 946747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 956747b715Smrg * DEALINGS IN THE SOFTWARE. 9605b261ecSmrg */ 9705b261ecSmrg 9805b261ecSmrg/* Routines to manage various kinds of resources: 9905b261ecSmrg * 10005b261ecSmrg * CreateNewResourceType, CreateNewResourceClass, InitClientResources, 10105b261ecSmrg * FakeClientID, AddResource, FreeResource, FreeClientResources, 10205b261ecSmrg * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange 10305b261ecSmrg */ 10405b261ecSmrg 10505b261ecSmrg/* 10605b261ecSmrg * A resource ID is a 32 bit quantity, the upper 2 bits of which are 10705b261ecSmrg * off-limits for client-visible resources. The next 8 bits are 10805b261ecSmrg * used as client ID, and the low 22 bits come from the client. 10905b261ecSmrg * A resource ID is "hashed" by extracting and xoring subfields 11005b261ecSmrg * (varying with the size of the hash table). 11105b261ecSmrg * 11205b261ecSmrg * It is sometimes necessary for the server to create an ID that looks 11305b261ecSmrg * like it belongs to a client. This ID, however, must not be one 11405b261ecSmrg * the client actually can create, or we have the potential for conflict. 11505b261ecSmrg * The 31st bit of the ID is reserved for the server's use for this 11605b261ecSmrg * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to 11705b261ecSmrg * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a 11805b261ecSmrg * resource "owned" by the client. 11905b261ecSmrg */ 12005b261ecSmrg 12105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 12205b261ecSmrg#include <dix-config.h> 12305b261ecSmrg#endif 12405b261ecSmrg 12505b261ecSmrg#include <X11/X.h> 12605b261ecSmrg#include "misc.h" 12705b261ecSmrg#include "os.h" 12805b261ecSmrg#include "resource.h" 12905b261ecSmrg#include "dixstruct.h" 13005b261ecSmrg#include "opaque.h" 13105b261ecSmrg#include "windowstr.h" 13205b261ecSmrg#include "dixfont.h" 13305b261ecSmrg#include "colormap.h" 13405b261ecSmrg#include "inputstr.h" 13505b261ecSmrg#include "dixevents.h" 13605b261ecSmrg#include "dixgrabs.h" 13705b261ecSmrg#include "cursor.h" 13805b261ecSmrg#ifdef PANORAMIX 13905b261ecSmrg#include "panoramiX.h" 14005b261ecSmrg#include "panoramiXsrv.h" 14105b261ecSmrg#endif 14205b261ecSmrg#include "xace.h" 14305b261ecSmrg#include <assert.h> 1446747b715Smrg#include "registry.h" 14505b261ecSmrg 14605b261ecSmrg#ifdef XSERVER_DTRACE 14705b261ecSmrg#include <sys/types.h> 14805b261ecSmrgtypedef const char *string; 14905b261ecSmrg#include "Xserver-dtrace.h" 15005b261ecSmrg 1514642e01fSmrg#define TypeNameString(t) LookupResourceName(t) 15205b261ecSmrg#endif 15305b261ecSmrg 15405b261ecSmrgstatic void RebuildTable( 15505b261ecSmrg int /*client*/ 15605b261ecSmrg); 15705b261ecSmrg 15805b261ecSmrg#define SERVER_MINID 32 15905b261ecSmrg 16005b261ecSmrg#define INITBUCKETS 64 16105b261ecSmrg#define INITHASHSIZE 6 16205b261ecSmrg#define MAXHASHSIZE 11 16305b261ecSmrg 16405b261ecSmrgtypedef struct _Resource { 16505b261ecSmrg struct _Resource *next; 16605b261ecSmrg XID id; 16705b261ecSmrg RESTYPE type; 16805b261ecSmrg pointer value; 16905b261ecSmrg} ResourceRec, *ResourcePtr; 17005b261ecSmrg 17105b261ecSmrgtypedef struct _ClientResource { 17205b261ecSmrg ResourcePtr *resources; 17305b261ecSmrg int elements; 17405b261ecSmrg int buckets; 17505b261ecSmrg int hashsize; /* log(2)(buckets) */ 17605b261ecSmrg XID fakeID; 17705b261ecSmrg XID endFakeID; 17805b261ecSmrg} ClientResourceRec; 17905b261ecSmrg 1806747b715SmrgRESTYPE lastResourceType; 18105b261ecSmrgstatic RESTYPE lastResourceClass; 1826747b715SmrgRESTYPE TypeMask; 1836747b715Smrg 1846747b715Smrgstruct ResourceType { 1856747b715Smrg DeleteType deleteFunc; 1866747b715Smrg int errorValue; 1876747b715Smrg}; 1886747b715Smrg 1896747b715Smrgstatic struct ResourceType *resourceTypes; 1906747b715Smrgstatic const struct ResourceType predefTypes[] = { 1916747b715Smrg [RT_NONE & (RC_LASTPREDEF - 1)] = { 1926747b715Smrg .deleteFunc = (DeleteType)NoopDDA, 1936747b715Smrg .errorValue = BadValue, 1946747b715Smrg }, 1956747b715Smrg [RT_WINDOW & (RC_LASTPREDEF - 1)] = { 1966747b715Smrg .deleteFunc = DeleteWindow, 1976747b715Smrg .errorValue = BadWindow, 1986747b715Smrg }, 1996747b715Smrg [RT_PIXMAP & (RC_LASTPREDEF - 1)] = { 2006747b715Smrg .deleteFunc = dixDestroyPixmap, 2016747b715Smrg .errorValue = BadPixmap, 2026747b715Smrg }, 2036747b715Smrg [RT_GC & (RC_LASTPREDEF - 1)] = { 2046747b715Smrg .deleteFunc = FreeGC, 2056747b715Smrg .errorValue = BadGC, 2066747b715Smrg }, 2076747b715Smrg [RT_FONT & (RC_LASTPREDEF - 1)] = { 2086747b715Smrg .deleteFunc = CloseFont, 2096747b715Smrg .errorValue = BadFont, 2106747b715Smrg }, 2116747b715Smrg [RT_CURSOR & (RC_LASTPREDEF - 1)] = { 2126747b715Smrg .deleteFunc = FreeCursor, 2136747b715Smrg .errorValue = BadCursor, 2146747b715Smrg }, 2156747b715Smrg [RT_COLORMAP & (RC_LASTPREDEF - 1)] = { 2166747b715Smrg .deleteFunc = FreeColormap, 2176747b715Smrg .errorValue = BadColor, 2186747b715Smrg }, 2196747b715Smrg [RT_CMAPENTRY & (RC_LASTPREDEF - 1)] = { 2206747b715Smrg .deleteFunc = FreeClientPixels, 2216747b715Smrg .errorValue = BadColor, 2226747b715Smrg }, 2236747b715Smrg [RT_OTHERCLIENT & (RC_LASTPREDEF - 1)] = { 2246747b715Smrg .deleteFunc = OtherClientGone, 2256747b715Smrg .errorValue = BadValue, 2266747b715Smrg }, 2276747b715Smrg [RT_PASSIVEGRAB & (RC_LASTPREDEF - 1)] = { 2286747b715Smrg .deleteFunc = DeletePassiveGrab, 2296747b715Smrg .errorValue = BadValue, 2306747b715Smrg }, 2316747b715Smrg}; 2326747b715Smrg 2336747b715SmrgCallbackListPtr ResourceStateCallback; 23405b261ecSmrg 2354642e01fSmrgstatic _X_INLINE void 2364642e01fSmrgCallResourceStateCallback(ResourceState state, ResourceRec *res) 23705b261ecSmrg{ 2384642e01fSmrg if (ResourceStateCallback) { 2394642e01fSmrg ResourceStateInfoRec rsi = { state, res->id, res->type, res->value }; 2404642e01fSmrg CallCallbacks(&ResourceStateCallback, &rsi); 2414642e01fSmrg } 24205b261ecSmrg} 24305b261ecSmrg 2446747b715SmrgRESTYPE 2456747b715SmrgCreateNewResourceType(DeleteType deleteFunc, char *name) 24605b261ecSmrg{ 24705b261ecSmrg RESTYPE next = lastResourceType + 1; 2486747b715Smrg struct ResourceType *types; 24905b261ecSmrg 25005b261ecSmrg if (next & lastResourceClass) 25105b261ecSmrg return 0; 2526747b715Smrg types = realloc(resourceTypes, (next + 1) * sizeof(*resourceTypes)); 2536747b715Smrg if (!types) 2544642e01fSmrg return 0; 25505b261ecSmrg 25605b261ecSmrg lastResourceType = next; 2576747b715Smrg resourceTypes = types; 2586747b715Smrg resourceTypes[next].deleteFunc = deleteFunc; 2596747b715Smrg resourceTypes[next].errorValue = BadValue; 2606747b715Smrg 2616747b715Smrg /* Called even if name is NULL, to remove any previous entry */ 2626747b715Smrg RegisterResourceName(next, name); 2636747b715Smrg 26405b261ecSmrg return next; 26505b261ecSmrg} 26605b261ecSmrg 2676747b715Smrgvoid 2686747b715SmrgSetResourceTypeErrorValue(RESTYPE type, int errorValue) 2696747b715Smrg{ 2706747b715Smrg resourceTypes[type & TypeMask].errorValue = errorValue; 2716747b715Smrg} 2726747b715Smrg 2736747b715SmrgRESTYPE 27405b261ecSmrgCreateNewResourceClass(void) 27505b261ecSmrg{ 27605b261ecSmrg RESTYPE next = lastResourceClass >> 1; 27705b261ecSmrg 27805b261ecSmrg if (next & lastResourceType) 27905b261ecSmrg return 0; 28005b261ecSmrg lastResourceClass = next; 28105b261ecSmrg TypeMask = next - 1; 28205b261ecSmrg return next; 28305b261ecSmrg} 28405b261ecSmrg 28505b261ecSmrgstatic ClientResourceRec clientTable[MAXCLIENTS]; 28605b261ecSmrg 28705b261ecSmrg/***************** 28805b261ecSmrg * InitClientResources 28905b261ecSmrg * When a new client is created, call this to allocate space 29005b261ecSmrg * in resource table 29105b261ecSmrg *****************/ 29205b261ecSmrg 29305b261ecSmrgBool 29405b261ecSmrgInitClientResources(ClientPtr client) 29505b261ecSmrg{ 29605b261ecSmrg int i, j; 29705b261ecSmrg 29805b261ecSmrg if (client == serverClient) 29905b261ecSmrg { 30005b261ecSmrg lastResourceType = RT_LASTPREDEF; 30105b261ecSmrg lastResourceClass = RC_LASTPREDEF; 30205b261ecSmrg TypeMask = RC_LASTPREDEF - 1; 3036747b715Smrg free(resourceTypes); 3046747b715Smrg resourceTypes = malloc(sizeof(predefTypes)); 3056747b715Smrg if (!resourceTypes) 30605b261ecSmrg return FALSE; 3076747b715Smrg memcpy(resourceTypes, predefTypes, sizeof(predefTypes)); 30805b261ecSmrg } 30905b261ecSmrg clientTable[i = client->index].resources = 3106747b715Smrg malloc(INITBUCKETS*sizeof(ResourcePtr)); 31105b261ecSmrg if (!clientTable[i].resources) 31205b261ecSmrg return FALSE; 31305b261ecSmrg clientTable[i].buckets = INITBUCKETS; 31405b261ecSmrg clientTable[i].elements = 0; 31505b261ecSmrg clientTable[i].hashsize = INITHASHSIZE; 31605b261ecSmrg /* Many IDs allocated from the server client are visible to clients, 31705b261ecSmrg * so we don't use the SERVER_BIT for them, but we have to start 31805b261ecSmrg * past the magic value constants used in the protocol. For normal 31905b261ecSmrg * clients, we can start from zero, with SERVER_BIT set. 32005b261ecSmrg */ 32105b261ecSmrg clientTable[i].fakeID = client->clientAsMask | 32205b261ecSmrg (client->index ? SERVER_BIT : SERVER_MINID); 32305b261ecSmrg clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1; 32405b261ecSmrg for (j=0; j<INITBUCKETS; j++) 32505b261ecSmrg { 3269ace9065Smrg clientTable[i].resources[j] = NULL; 32705b261ecSmrg } 32805b261ecSmrg return TRUE; 32905b261ecSmrg} 33005b261ecSmrg 33105b261ecSmrg 33205b261ecSmrgstatic int 33305b261ecSmrgHash(int client, XID id) 33405b261ecSmrg{ 33505b261ecSmrg id &= RESOURCE_ID_MASK; 33605b261ecSmrg switch (clientTable[client].hashsize) 33705b261ecSmrg { 33805b261ecSmrg case 6: 33905b261ecSmrg return ((int)(0x03F & (id ^ (id>>6) ^ (id>>12)))); 34005b261ecSmrg case 7: 34105b261ecSmrg return ((int)(0x07F & (id ^ (id>>7) ^ (id>>13)))); 34205b261ecSmrg case 8: 34305b261ecSmrg return ((int)(0x0FF & (id ^ (id>>8) ^ (id>>16)))); 34405b261ecSmrg case 9: 34505b261ecSmrg return ((int)(0x1FF & (id ^ (id>>9)))); 34605b261ecSmrg case 10: 34705b261ecSmrg return ((int)(0x3FF & (id ^ (id>>10)))); 34805b261ecSmrg case 11: 34905b261ecSmrg return ((int)(0x7FF & (id ^ (id>>11)))); 35005b261ecSmrg } 35105b261ecSmrg return -1; 35205b261ecSmrg} 35305b261ecSmrg 35405b261ecSmrgstatic XID 35505b261ecSmrgAvailableID( 35605b261ecSmrg int client, 35705b261ecSmrg XID id, 35805b261ecSmrg XID maxid, 35905b261ecSmrg XID goodid) 36005b261ecSmrg{ 36105b261ecSmrg ResourcePtr res; 36205b261ecSmrg 36305b261ecSmrg if ((goodid >= id) && (goodid <= maxid)) 36405b261ecSmrg return goodid; 36505b261ecSmrg for (; id <= maxid; id++) 36605b261ecSmrg { 36705b261ecSmrg res = clientTable[client].resources[Hash(client, id)]; 36805b261ecSmrg while (res && (res->id != id)) 36905b261ecSmrg res = res->next; 37005b261ecSmrg if (!res) 37105b261ecSmrg return id; 37205b261ecSmrg } 37305b261ecSmrg return 0; 37405b261ecSmrg} 37505b261ecSmrg 3764642e01fSmrgvoid 37705b261ecSmrgGetXIDRange(int client, Bool server, XID *minp, XID *maxp) 37805b261ecSmrg{ 37905b261ecSmrg XID id, maxid; 38005b261ecSmrg ResourcePtr *resp; 38105b261ecSmrg ResourcePtr res; 38205b261ecSmrg int i; 38305b261ecSmrg XID goodid; 38405b261ecSmrg 38505b261ecSmrg id = (Mask)client << CLIENTOFFSET; 38605b261ecSmrg if (server) 38705b261ecSmrg id |= client ? SERVER_BIT : SERVER_MINID; 38805b261ecSmrg maxid = id | RESOURCE_ID_MASK; 38905b261ecSmrg goodid = 0; 39005b261ecSmrg for (resp = clientTable[client].resources, i = clientTable[client].buckets; 39105b261ecSmrg --i >= 0;) 39205b261ecSmrg { 39305b261ecSmrg for (res = *resp++; res; res = res->next) 39405b261ecSmrg { 39505b261ecSmrg if ((res->id < id) || (res->id > maxid)) 39605b261ecSmrg continue; 39705b261ecSmrg if (((res->id - id) >= (maxid - res->id)) ? 39805b261ecSmrg (goodid = AvailableID(client, id, res->id - 1, goodid)) : 39905b261ecSmrg !(goodid = AvailableID(client, res->id + 1, maxid, goodid))) 40005b261ecSmrg maxid = res->id - 1; 40105b261ecSmrg else 40205b261ecSmrg id = res->id + 1; 40305b261ecSmrg } 40405b261ecSmrg } 40505b261ecSmrg if (id > maxid) 40605b261ecSmrg id = maxid = 0; 40705b261ecSmrg *minp = id; 40805b261ecSmrg *maxp = maxid; 40905b261ecSmrg} 41005b261ecSmrg 41105b261ecSmrg/** 41205b261ecSmrg * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function. 41305b261ecSmrg * This function tries to find count unused XIDs for the given client. It 41405b261ecSmrg * puts the IDs in the array pids and returns the number found, which should 41505b261ecSmrg * almost always be the number requested. 41605b261ecSmrg * 41705b261ecSmrg * The circumstances that lead to a call to this function are very rare. 41805b261ecSmrg * Xlib must run out of IDs while trying to generate a request that wants 41905b261ecSmrg * multiple ID's, like the Multi-buffering CreateImageBuffers request. 42005b261ecSmrg * 42105b261ecSmrg * No rocket science in the implementation; just iterate over all 42205b261ecSmrg * possible IDs for the given client and pick the first count IDs 42305b261ecSmrg * that aren't in use. A more efficient algorithm could probably be 42405b261ecSmrg * invented, but this will be used so rarely that this should suffice. 42505b261ecSmrg */ 42605b261ecSmrg 4274642e01fSmrgunsigned int 42805b261ecSmrgGetXIDList(ClientPtr pClient, unsigned count, XID *pids) 42905b261ecSmrg{ 43005b261ecSmrg unsigned int found = 0; 4316747b715Smrg XID rc, id = pClient->clientAsMask; 43205b261ecSmrg XID maxid; 4336747b715Smrg pointer val; 43405b261ecSmrg 43505b261ecSmrg maxid = id | RESOURCE_ID_MASK; 43605b261ecSmrg while ( (found < count) && (id <= maxid) ) 43705b261ecSmrg { 4386747b715Smrg rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient, 4396747b715Smrg DixGetAttrAccess); 4406747b715Smrg if (rc == BadValue) 44105b261ecSmrg { 44205b261ecSmrg pids[found++] = id; 44305b261ecSmrg } 44405b261ecSmrg id++; 44505b261ecSmrg } 44605b261ecSmrg return found; 44705b261ecSmrg} 44805b261ecSmrg 44905b261ecSmrg/* 45005b261ecSmrg * Return the next usable fake client ID. 45105b261ecSmrg * 45205b261ecSmrg * Normally this is just the next one in line, but if we've used the last 45305b261ecSmrg * in the range, we need to find a new range of safe IDs to avoid 45405b261ecSmrg * over-running another client. 45505b261ecSmrg */ 45605b261ecSmrg 4576747b715SmrgXID 45805b261ecSmrgFakeClientID(int client) 45905b261ecSmrg{ 46005b261ecSmrg XID id, maxid; 46105b261ecSmrg 46205b261ecSmrg id = clientTable[client].fakeID++; 46305b261ecSmrg if (id != clientTable[client].endFakeID) 46405b261ecSmrg return id; 46505b261ecSmrg GetXIDRange(client, TRUE, &id, &maxid); 46605b261ecSmrg if (!id) { 46705b261ecSmrg if (!client) 46805b261ecSmrg FatalError("FakeClientID: server internal ids exhausted\n"); 46905b261ecSmrg MarkClientException(clients[client]); 47005b261ecSmrg id = ((Mask)client << CLIENTOFFSET) | (SERVER_BIT * 3); 47105b261ecSmrg maxid = id | RESOURCE_ID_MASK; 47205b261ecSmrg } 47305b261ecSmrg clientTable[client].fakeID = id + 1; 47405b261ecSmrg clientTable[client].endFakeID = maxid + 1; 47505b261ecSmrg return id; 47605b261ecSmrg} 47705b261ecSmrg 4786747b715SmrgBool 47905b261ecSmrgAddResource(XID id, RESTYPE type, pointer value) 48005b261ecSmrg{ 48105b261ecSmrg int client; 48205b261ecSmrg ClientResourceRec *rrec; 48305b261ecSmrg ResourcePtr res, *head; 48405b261ecSmrg 48505b261ecSmrg#ifdef XSERVER_DTRACE 48605b261ecSmrg XSERVER_RESOURCE_ALLOC(id, type, value, TypeNameString(type)); 48705b261ecSmrg#endif 48805b261ecSmrg client = CLIENT_ID(id); 48905b261ecSmrg rrec = &clientTable[client]; 49005b261ecSmrg if (!rrec->buckets) 49105b261ecSmrg { 4924642e01fSmrg ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n", 49305b261ecSmrg (unsigned long)id, type, (unsigned long)value, client); 49405b261ecSmrg FatalError("client not in use\n"); 49505b261ecSmrg } 49605b261ecSmrg if ((rrec->elements >= 4*rrec->buckets) && 49705b261ecSmrg (rrec->hashsize < MAXHASHSIZE)) 49805b261ecSmrg RebuildTable(client); 49905b261ecSmrg head = &rrec->resources[Hash(client, id)]; 5006747b715Smrg res = malloc(sizeof(ResourceRec)); 50105b261ecSmrg if (!res) 50205b261ecSmrg { 5036747b715Smrg (*resourceTypes[type & TypeMask].deleteFunc)(value, id); 50405b261ecSmrg return FALSE; 50505b261ecSmrg } 50605b261ecSmrg res->next = *head; 50705b261ecSmrg res->id = id; 50805b261ecSmrg res->type = type; 50905b261ecSmrg res->value = value; 51005b261ecSmrg *head = res; 51105b261ecSmrg rrec->elements++; 5124642e01fSmrg CallResourceStateCallback(ResourceStateAdding, res); 51305b261ecSmrg return TRUE; 51405b261ecSmrg} 51505b261ecSmrg 51605b261ecSmrgstatic void 51705b261ecSmrgRebuildTable(int client) 51805b261ecSmrg{ 51905b261ecSmrg int j; 52005b261ecSmrg ResourcePtr res, next; 52105b261ecSmrg ResourcePtr **tails, *resources; 52205b261ecSmrg ResourcePtr **tptr, *rptr; 52305b261ecSmrg 52405b261ecSmrg /* 52505b261ecSmrg * For now, preserve insertion order, since some ddx layers depend 52605b261ecSmrg * on resources being free in the opposite order they are added. 52705b261ecSmrg */ 52805b261ecSmrg 52905b261ecSmrg j = 2 * clientTable[client].buckets; 5306747b715Smrg tails = malloc(j * sizeof(ResourcePtr *)); 53105b261ecSmrg if (!tails) 53205b261ecSmrg return; 5336747b715Smrg resources = malloc(j * sizeof(ResourcePtr)); 53405b261ecSmrg if (!resources) 53505b261ecSmrg { 5366747b715Smrg free(tails); 53705b261ecSmrg return; 53805b261ecSmrg } 53905b261ecSmrg for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) 54005b261ecSmrg { 5419ace9065Smrg *rptr = NULL; 54205b261ecSmrg *tptr = rptr; 54305b261ecSmrg } 54405b261ecSmrg clientTable[client].hashsize++; 54505b261ecSmrg for (j = clientTable[client].buckets, 54605b261ecSmrg rptr = clientTable[client].resources; 54705b261ecSmrg --j >= 0; 54805b261ecSmrg rptr++) 54905b261ecSmrg { 55005b261ecSmrg for (res = *rptr; res; res = next) 55105b261ecSmrg { 55205b261ecSmrg next = res->next; 5539ace9065Smrg res->next = NULL; 55405b261ecSmrg tptr = &tails[Hash(client, res->id)]; 55505b261ecSmrg **tptr = res; 55605b261ecSmrg *tptr = &res->next; 55705b261ecSmrg } 55805b261ecSmrg } 5596747b715Smrg free(tails); 56005b261ecSmrg clientTable[client].buckets *= 2; 5616747b715Smrg free(clientTable[client].resources); 56205b261ecSmrg clientTable[client].resources = resources; 56305b261ecSmrg} 56405b261ecSmrg 5656747b715Smrgvoid 56605b261ecSmrgFreeResource(XID id, RESTYPE skipDeleteFuncType) 56705b261ecSmrg{ 56805b261ecSmrg int cid; 56905b261ecSmrg ResourcePtr res; 57005b261ecSmrg ResourcePtr *prev, *head; 57105b261ecSmrg int *eltptr; 57205b261ecSmrg int elements; 57305b261ecSmrg 57405b261ecSmrg if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) 57505b261ecSmrg { 57605b261ecSmrg head = &clientTable[cid].resources[Hash(cid, id)]; 57705b261ecSmrg eltptr = &clientTable[cid].elements; 57805b261ecSmrg 57905b261ecSmrg prev = head; 58005b261ecSmrg while ( (res = *prev) ) 58105b261ecSmrg { 58205b261ecSmrg if (res->id == id) 58305b261ecSmrg { 58405b261ecSmrg RESTYPE rtype = res->type; 58505b261ecSmrg 58605b261ecSmrg#ifdef XSERVER_DTRACE 58705b261ecSmrg XSERVER_RESOURCE_FREE(res->id, res->type, 58805b261ecSmrg res->value, TypeNameString(res->type)); 58905b261ecSmrg#endif 59005b261ecSmrg *prev = res->next; 59105b261ecSmrg elements = --*eltptr; 5924642e01fSmrg 5934642e01fSmrg CallResourceStateCallback(ResourceStateFreeing, res); 5944642e01fSmrg 59505b261ecSmrg if (rtype != skipDeleteFuncType) 5966747b715Smrg (*resourceTypes[rtype & TypeMask].deleteFunc)(res->value, res->id); 5976747b715Smrg free(res); 59805b261ecSmrg if (*eltptr != elements) 59905b261ecSmrg prev = head; /* prev may no longer be valid */ 60005b261ecSmrg } 60105b261ecSmrg else 60205b261ecSmrg prev = &res->next; 60305b261ecSmrg } 60405b261ecSmrg } 60505b261ecSmrg} 60605b261ecSmrg 60705b261ecSmrg 6086747b715Smrgvoid 60905b261ecSmrgFreeResourceByType(XID id, RESTYPE type, Bool skipFree) 61005b261ecSmrg{ 61105b261ecSmrg int cid; 61205b261ecSmrg ResourcePtr res; 61305b261ecSmrg ResourcePtr *prev, *head; 61405b261ecSmrg if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) 61505b261ecSmrg { 61605b261ecSmrg head = &clientTable[cid].resources[Hash(cid, id)]; 61705b261ecSmrg 61805b261ecSmrg prev = head; 61905b261ecSmrg while ( (res = *prev) ) 62005b261ecSmrg { 62105b261ecSmrg if (res->id == id && res->type == type) 62205b261ecSmrg { 62305b261ecSmrg#ifdef XSERVER_DTRACE 62405b261ecSmrg XSERVER_RESOURCE_FREE(res->id, res->type, 62505b261ecSmrg res->value, TypeNameString(res->type)); 62605b261ecSmrg#endif 62705b261ecSmrg *prev = res->next; 6286747b715Smrg clientTable[cid].elements--; 6294642e01fSmrg 6304642e01fSmrg CallResourceStateCallback(ResourceStateFreeing, res); 6314642e01fSmrg 63205b261ecSmrg if (!skipFree) 6336747b715Smrg (*resourceTypes[type & TypeMask].deleteFunc)(res->value, res->id); 6346747b715Smrg free(res); 63505b261ecSmrg break; 63605b261ecSmrg } 63705b261ecSmrg else 63805b261ecSmrg prev = &res->next; 63905b261ecSmrg } 64005b261ecSmrg } 64105b261ecSmrg} 64205b261ecSmrg 64305b261ecSmrg/* 64405b261ecSmrg * Change the value associated with a resource id. Caller 64505b261ecSmrg * is responsible for "doing the right thing" with the old 64605b261ecSmrg * data 64705b261ecSmrg */ 64805b261ecSmrg 6496747b715SmrgBool 65005b261ecSmrgChangeResourceValue (XID id, RESTYPE rtype, pointer value) 65105b261ecSmrg{ 65205b261ecSmrg int cid; 65305b261ecSmrg ResourcePtr res; 65405b261ecSmrg 65505b261ecSmrg if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) 65605b261ecSmrg { 65705b261ecSmrg res = clientTable[cid].resources[Hash(cid, id)]; 65805b261ecSmrg 65905b261ecSmrg for (; res; res = res->next) 66005b261ecSmrg if ((res->id == id) && (res->type == rtype)) 66105b261ecSmrg { 66205b261ecSmrg res->value = value; 66305b261ecSmrg return TRUE; 66405b261ecSmrg } 66505b261ecSmrg } 66605b261ecSmrg return FALSE; 66705b261ecSmrg} 66805b261ecSmrg 66905b261ecSmrg/* Note: if func adds or deletes resources, then func can get called 67005b261ecSmrg * more than once for some resources. If func adds new resources, 67105b261ecSmrg * func might or might not get called for them. func cannot both 67205b261ecSmrg * add and delete an equal number of resources! 67305b261ecSmrg */ 67405b261ecSmrg 6756747b715Smrgvoid 67605b261ecSmrgFindClientResourcesByType( 67705b261ecSmrg ClientPtr client, 67805b261ecSmrg RESTYPE type, 67905b261ecSmrg FindResType func, 68005b261ecSmrg pointer cdata 68105b261ecSmrg){ 68205b261ecSmrg ResourcePtr *resources; 68305b261ecSmrg ResourcePtr this, next; 68405b261ecSmrg int i, elements; 68505b261ecSmrg int *eltptr; 68605b261ecSmrg 68705b261ecSmrg if (!client) 68805b261ecSmrg client = serverClient; 68905b261ecSmrg 69005b261ecSmrg resources = clientTable[client->index].resources; 69105b261ecSmrg eltptr = &clientTable[client->index].elements; 69205b261ecSmrg for (i = 0; i < clientTable[client->index].buckets; i++) 69305b261ecSmrg { 69405b261ecSmrg for (this = resources[i]; this; this = next) 69505b261ecSmrg { 69605b261ecSmrg next = this->next; 69705b261ecSmrg if (!type || this->type == type) { 69805b261ecSmrg elements = *eltptr; 69905b261ecSmrg (*func)(this->value, this->id, cdata); 70005b261ecSmrg if (*eltptr != elements) 70105b261ecSmrg next = resources[i]; /* start over */ 70205b261ecSmrg } 70305b261ecSmrg } 70405b261ecSmrg } 70505b261ecSmrg} 70605b261ecSmrg 7076747b715Smrgvoid 70805b261ecSmrgFindAllClientResources( 70905b261ecSmrg ClientPtr client, 71005b261ecSmrg FindAllRes func, 71105b261ecSmrg pointer cdata 71205b261ecSmrg){ 71305b261ecSmrg ResourcePtr *resources; 71405b261ecSmrg ResourcePtr this, next; 71505b261ecSmrg int i, elements; 71605b261ecSmrg int *eltptr; 71705b261ecSmrg 71805b261ecSmrg if (!client) 71905b261ecSmrg client = serverClient; 72005b261ecSmrg 72105b261ecSmrg resources = clientTable[client->index].resources; 72205b261ecSmrg eltptr = &clientTable[client->index].elements; 72305b261ecSmrg for (i = 0; i < clientTable[client->index].buckets; i++) 72405b261ecSmrg { 72505b261ecSmrg for (this = resources[i]; this; this = next) 72605b261ecSmrg { 72705b261ecSmrg next = this->next; 72805b261ecSmrg elements = *eltptr; 72905b261ecSmrg (*func)(this->value, this->id, this->type, cdata); 73005b261ecSmrg if (*eltptr != elements) 73105b261ecSmrg next = resources[i]; /* start over */ 73205b261ecSmrg } 73305b261ecSmrg } 73405b261ecSmrg} 73505b261ecSmrg 73605b261ecSmrg 73705b261ecSmrgpointer 73805b261ecSmrgLookupClientResourceComplex( 73905b261ecSmrg ClientPtr client, 74005b261ecSmrg RESTYPE type, 74105b261ecSmrg FindComplexResType func, 74205b261ecSmrg pointer cdata 74305b261ecSmrg){ 74405b261ecSmrg ResourcePtr *resources; 7456747b715Smrg ResourcePtr this, next; 7466747b715Smrg pointer value; 74705b261ecSmrg int i; 74805b261ecSmrg 74905b261ecSmrg if (!client) 75005b261ecSmrg client = serverClient; 75105b261ecSmrg 75205b261ecSmrg resources = clientTable[client->index].resources; 75305b261ecSmrg for (i = 0; i < clientTable[client->index].buckets; i++) { 7546747b715Smrg for (this = resources[i]; this; this = next) { 7556747b715Smrg next = this->next; 75605b261ecSmrg if (!type || this->type == type) { 7576747b715Smrg /* workaround func freeing the type as DRI1 does */ 7586747b715Smrg value = this->value; 7596747b715Smrg if((*func)(value, this->id, cdata)) 7606747b715Smrg return value; 76105b261ecSmrg } 76205b261ecSmrg } 76305b261ecSmrg } 76405b261ecSmrg return NULL; 76505b261ecSmrg} 76605b261ecSmrg 76705b261ecSmrg 76805b261ecSmrgvoid 76905b261ecSmrgFreeClientNeverRetainResources(ClientPtr client) 77005b261ecSmrg{ 77105b261ecSmrg ResourcePtr *resources; 77205b261ecSmrg ResourcePtr this; 77305b261ecSmrg ResourcePtr *prev; 7746747b715Smrg int j, elements; 7756747b715Smrg int *eltptr; 77605b261ecSmrg 77705b261ecSmrg if (!client) 77805b261ecSmrg return; 77905b261ecSmrg 78005b261ecSmrg resources = clientTable[client->index].resources; 7816747b715Smrg eltptr = &clientTable[client->index].elements; 78205b261ecSmrg for (j=0; j < clientTable[client->index].buckets; j++) 78305b261ecSmrg { 78405b261ecSmrg prev = &resources[j]; 78505b261ecSmrg while ( (this = *prev) ) 78605b261ecSmrg { 78705b261ecSmrg RESTYPE rtype = this->type; 78805b261ecSmrg if (rtype & RC_NEVERRETAIN) 78905b261ecSmrg { 79005b261ecSmrg#ifdef XSERVER_DTRACE 79105b261ecSmrg XSERVER_RESOURCE_FREE(this->id, this->type, 79205b261ecSmrg this->value, TypeNameString(this->type)); 79305b261ecSmrg#endif 79405b261ecSmrg *prev = this->next; 7956747b715Smrg clientTable[client->index].elements--; 7964642e01fSmrg 7974642e01fSmrg CallResourceStateCallback(ResourceStateFreeing, this); 7984642e01fSmrg 7996747b715Smrg elements = *eltptr; 8006747b715Smrg (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id); 8016747b715Smrg free(this); 8026747b715Smrg if (*eltptr != elements) 8036747b715Smrg prev = &resources[j]; /* prev may no longer be valid */ 80405b261ecSmrg } 80505b261ecSmrg else 80605b261ecSmrg prev = &this->next; 80705b261ecSmrg } 80805b261ecSmrg } 80905b261ecSmrg} 81005b261ecSmrg 81105b261ecSmrgvoid 81205b261ecSmrgFreeClientResources(ClientPtr client) 81305b261ecSmrg{ 81405b261ecSmrg ResourcePtr *resources; 81505b261ecSmrg ResourcePtr this; 81605b261ecSmrg int j; 81705b261ecSmrg 81805b261ecSmrg /* This routine shouldn't be called with a null client, but just in 81905b261ecSmrg case ... */ 82005b261ecSmrg 82105b261ecSmrg if (!client) 82205b261ecSmrg return; 82305b261ecSmrg 82405b261ecSmrg HandleSaveSet(client); 82505b261ecSmrg 82605b261ecSmrg resources = clientTable[client->index].resources; 82705b261ecSmrg for (j=0; j < clientTable[client->index].buckets; j++) 82805b261ecSmrg { 82905b261ecSmrg /* It may seem silly to update the head of this resource list as 83005b261ecSmrg we delete the members, since the entire list will be deleted any way, 83105b261ecSmrg but there are some resource deletion functions "FreeClientPixels" for 83205b261ecSmrg one which do a LookupID on another resource id (a Colormap id in this 83305b261ecSmrg case), so the resource list must be kept valid up to the point that 83405b261ecSmrg it is deleted, so every time we delete a resource, we must update the 83505b261ecSmrg head, just like in FreeResource. I hope that this doesn't slow down 83605b261ecSmrg mass deletion appreciably. PRH */ 83705b261ecSmrg 83805b261ecSmrg ResourcePtr *head; 83905b261ecSmrg 84005b261ecSmrg head = &resources[j]; 84105b261ecSmrg 84205b261ecSmrg for (this = *head; this; this = *head) 84305b261ecSmrg { 84405b261ecSmrg RESTYPE rtype = this->type; 84505b261ecSmrg#ifdef XSERVER_DTRACE 84605b261ecSmrg XSERVER_RESOURCE_FREE(this->id, this->type, 84705b261ecSmrg this->value, TypeNameString(this->type)); 84805b261ecSmrg#endif 84905b261ecSmrg *head = this->next; 8506747b715Smrg clientTable[client->index].elements--; 8514642e01fSmrg 8524642e01fSmrg CallResourceStateCallback(ResourceStateFreeing, this); 8534642e01fSmrg 8546747b715Smrg (*resourceTypes[rtype & TypeMask].deleteFunc)(this->value, this->id); 8556747b715Smrg free(this); 85605b261ecSmrg } 85705b261ecSmrg } 8586747b715Smrg free(clientTable[client->index].resources); 85905b261ecSmrg clientTable[client->index].resources = NULL; 86005b261ecSmrg clientTable[client->index].buckets = 0; 86105b261ecSmrg} 86205b261ecSmrg 86305b261ecSmrgvoid 86405b261ecSmrgFreeAllResources(void) 86505b261ecSmrg{ 86605b261ecSmrg int i; 86705b261ecSmrg 86805b261ecSmrg for (i = currentMaxClients; --i >= 0; ) 86905b261ecSmrg { 87005b261ecSmrg if (clientTable[i].buckets) 87105b261ecSmrg FreeClientResources(clients[i]); 87205b261ecSmrg } 87305b261ecSmrg} 87405b261ecSmrg 8756747b715SmrgBool 87605b261ecSmrgLegalNewID(XID id, ClientPtr client) 87705b261ecSmrg{ 8786747b715Smrg pointer val; 8796747b715Smrg int rc; 88005b261ecSmrg 88105b261ecSmrg#ifdef PANORAMIX 88205b261ecSmrg XID minid, maxid; 88305b261ecSmrg 8849ace9065Smrg if (!noPanoramiXExtension) { 8859ace9065Smrg minid = client->clientAsMask | (client->index ? 8869ace9065Smrg SERVER_BIT : SERVER_MINID); 8879ace9065Smrg maxid = (clientTable[client->index].fakeID | RESOURCE_ID_MASK) + 1; 8889ace9065Smrg if ((id >= minid) && (id <= maxid)) 8899ace9065Smrg return TRUE; 8909ace9065Smrg } 89105b261ecSmrg#endif /* PANORAMIX */ 8929ace9065Smrg if (client->clientAsMask == (id & ~RESOURCE_ID_MASK)) 8939ace9065Smrg { 8949ace9065Smrg rc = dixLookupResourceByClass(&val, id, RC_ANY, serverClient, 8959ace9065Smrg DixGetAttrAccess); 8969ace9065Smrg return rc == BadValue; 8979ace9065Smrg } 8989ace9065Smrg return FALSE; 89905b261ecSmrg} 90005b261ecSmrg 9016747b715Smrgint 902b86d567bSmrgdixLookupResourceByType(pointer *result, XID id, RESTYPE rtype, 903b86d567bSmrg ClientPtr client, Mask mode) 90405b261ecSmrg{ 9054642e01fSmrg int cid = CLIENT_ID(id); 90605b261ecSmrg ResourcePtr res = NULL; 90705b261ecSmrg 9084642e01fSmrg *result = NULL; 9096747b715Smrg if ((rtype & TypeMask) > lastResourceType) 9106747b715Smrg return BadImplementation; 9114642e01fSmrg 9124642e01fSmrg if ((cid < MAXCLIENTS) && clientTable[cid].buckets) { 91305b261ecSmrg res = clientTable[cid].resources[Hash(cid, id)]; 91405b261ecSmrg 91505b261ecSmrg for (; res; res = res->next) 916b86d567bSmrg if (res->id == id && res->type == rtype) 917b86d567bSmrg break; 918b86d567bSmrg } 919b86d567bSmrg if (!res) 9206747b715Smrg return resourceTypes[rtype & TypeMask].errorValue; 921b86d567bSmrg 922b86d567bSmrg if (client) { 923b86d567bSmrg client->errorValue = id; 924b86d567bSmrg cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, 925b86d567bSmrg res->value, RT_NONE, NULL, mode); 9266747b715Smrg if (cid == BadValue) 9276747b715Smrg return resourceTypes[rtype & TypeMask].errorValue; 928b86d567bSmrg if (cid != Success) 929b86d567bSmrg return cid; 930b86d567bSmrg } 931b86d567bSmrg 932b86d567bSmrg *result = res->value; 933b86d567bSmrg return Success; 934b86d567bSmrg} 935b86d567bSmrg 9366747b715Smrgint 937b86d567bSmrgdixLookupResourceByClass(pointer *result, XID id, RESTYPE rclass, 938b86d567bSmrg ClientPtr client, Mask mode) 939b86d567bSmrg{ 940b86d567bSmrg int cid = CLIENT_ID(id); 941b86d567bSmrg ResourcePtr res = NULL; 942b86d567bSmrg 943b86d567bSmrg *result = NULL; 944b86d567bSmrg 945b86d567bSmrg if ((cid < MAXCLIENTS) && clientTable[cid].buckets) { 946b86d567bSmrg res = clientTable[cid].resources[Hash(cid, id)]; 947b86d567bSmrg 948b86d567bSmrg for (; res; res = res->next) 949b86d567bSmrg if (res->id == id && (res->type & rclass)) 95005b261ecSmrg break; 95105b261ecSmrg } 9524642e01fSmrg if (!res) 9534642e01fSmrg return BadValue; 9544642e01fSmrg 9554642e01fSmrg if (client) { 9564642e01fSmrg client->errorValue = id; 9574642e01fSmrg cid = XaceHook(XACE_RESOURCE_ACCESS, client, id, res->type, 9584642e01fSmrg res->value, RT_NONE, NULL, mode); 9594642e01fSmrg if (cid != Success) 9604642e01fSmrg return cid; 9614642e01fSmrg } 96205b261ecSmrg 9634642e01fSmrg *result = res->value; 9644642e01fSmrg return Success; 96505b261ecSmrg} 966