123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845 |
- /************************************************************
- Copyright 1987, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ********************************************************/
- /* The panoramix components contained the following notice */
- /*****************************************************************
- Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
- BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of Digital Equipment Corporation
- shall not be used in advertising or otherwise to promote the sale, use or other
- dealings in this Software without prior written authorization from Digital
- Equipment Corporation.
- ******************************************************************/
- /* Routines to manage various kinds of resources:
- *
- * CreateNewResourceType, InitClientResources,
- * FakeClientID, AddResource, FreeResource, FreeClientResources,
- * FreeAllResources, LookupIDByType, LookupIDByClass, GetXIDRange
- */
- /*
- * A resource ID is a 32 bit quantity, the upper 2 bits of which are
- * off-limits for client-visible resources. The next 8 bits are
- * used as client ID, and the low 22 bits come from the client.
- * A resource ID is "hashed" by extracting and xoring subfields
- * (varying with the size of the hash table).
- *
- * It is sometimes necessary for the server to create an ID that looks
- * like it belongs to a client. This ID, however, must not be one
- * the client actually can create, or we have the potential for conflict.
- * The 31st bit of the ID is reserved for the server's use for this
- * purpose. By setting CLIENT_ID(id) to the client, the SERVER_BIT to
- * 1, and an otherwise arbitrary ID in the low 22 bits, we can create a
- * resource "owned" by the client.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <X11/X.h>
- #include "misc.h"
- #include "os.h"
- #include "resource.h"
- #include "dixstruct.h"
- #include "opaque.h"
- #include "windowstr.h"
- #include "dixfont.h"
- #include "colormap.h"
- #include "inputstr.h"
- #include "dixevents.h"
- #include "dixgrabs.h"
- #include "cursor.h"
- #include <assert.h>
- static void RebuildTable(int /*client */
- );
- #define SERVER_MINID 32
- #define INITBUCKETS 64
- #define INITHASHSIZE 6
- #define MAXHASHSIZE 11
- typedef struct _Resource {
- struct _Resource *next;
- XID id;
- RESTYPE type;
- pointer value;
- } ResourceRec, *ResourcePtr;
- #define NullResource ((ResourcePtr)NULL)
- typedef struct _ClientResource {
- ResourcePtr *resources;
- int elements;
- int buckets;
- int hashsize; /* log(2)(buckets) */
- XID fakeID;
- XID endFakeID;
- XID expectID;
- } ClientResourceRec;
- _X_EXPORT RESTYPE lastResourceType;
- static RESTYPE lastResourceClass;
- _X_EXPORT RESTYPE TypeMask;
- static DeleteType *DeleteFuncs = (DeleteType *) NULL;
- #ifdef XResExtension
- _X_EXPORT Atom *ResourceNames = NULL;
- _X_EXPORT void
- RegisterResourceName(RESTYPE type, char *name)
- {
- ResourceNames[type & TypeMask] = MakeAtom(name, strlen(name), TRUE);
- }
- #endif
- _X_EXPORT RESTYPE
- CreateNewResourceType(DeleteType deleteFunc)
- {
- RESTYPE next = lastResourceType + 1;
- DeleteType *funcs;
- if (next & lastResourceClass)
- return 0;
- funcs = (DeleteType *) realloc(DeleteFuncs,
- (next + 1) * sizeof(DeleteType));
- if (!funcs)
- return 0;
- #ifdef XResExtension
- {
- Atom *newnames;
- newnames = realloc(ResourceNames, (next + 1) * sizeof(Atom));
- if (!newnames)
- return 0;
- ResourceNames = newnames;
- ResourceNames[next] = 0;
- }
- #endif
- lastResourceType = next;
- DeleteFuncs = funcs;
- DeleteFuncs[next] = deleteFunc;
- return next;
- }
- ClientResourceRec clientTable[MAXCLIENTS];
- /*****************
- * InitClientResources
- * When a new client is created, call this to allocate space
- * in resource table
- *****************/
- Bool
- InitClientResources(ClientPtr client)
- {
- int i, j;
- if (client == serverClient) {
- lastResourceType = RT_LASTPREDEF;
- lastResourceClass = RC_LASTPREDEF;
- TypeMask = RC_LASTPREDEF - 1;
- if (DeleteFuncs)
- free(DeleteFuncs);
- DeleteFuncs = malloc((lastResourceType + 1) *
- sizeof(DeleteType));
- if (!DeleteFuncs)
- return FALSE;
- DeleteFuncs[RT_NONE & TypeMask] = (DeleteType) NoopDDA;
- DeleteFuncs[RT_WINDOW & TypeMask] = DeleteWindow;
- DeleteFuncs[RT_PIXMAP & TypeMask] = dixDestroyPixmap;
- DeleteFuncs[RT_GC & TypeMask] = FreeGC;
- DeleteFuncs[RT_FONT & TypeMask] = CloseFont;
- DeleteFuncs[RT_CURSOR & TypeMask] = FreeCursor;
- DeleteFuncs[RT_COLORMAP & TypeMask] = FreeColormap;
- DeleteFuncs[RT_CMAPENTRY & TypeMask] = FreeClientPixels;
- DeleteFuncs[RT_OTHERCLIENT & TypeMask] = OtherClientGone;
- DeleteFuncs[RT_PASSIVEGRAB & TypeMask] = DeletePassiveGrab;
- #ifdef XResExtension
- if (ResourceNames)
- free(ResourceNames);
- ResourceNames = malloc((lastResourceType + 1) * sizeof(Atom));
- if (!ResourceNames)
- return FALSE;
- #endif
- }
- clientTable[i = client->index].resources =
- malloc(INITBUCKETS * sizeof(ResourcePtr));
- if (!clientTable[i].resources)
- return FALSE;
- clientTable[i].buckets = INITBUCKETS;
- clientTable[i].elements = 0;
- clientTable[i].hashsize = INITHASHSIZE;
- /* Many IDs allocated from the server client are visible to clients,
- * so we don't use the SERVER_BIT for them, but we have to start
- * past the magic value constants used in the protocol. For normal
- * clients, we can start from zero, with SERVER_BIT set.
- */
- clientTable[i].fakeID = client->clientAsMask |
- (client->index ? SERVER_BIT : SERVER_MINID);
- clientTable[i].endFakeID = (clientTable[i].fakeID | RESOURCE_ID_MASK) + 1;
- clientTable[i].expectID = client->clientAsMask;
- for (j = 0; j < INITBUCKETS; j++) {
- clientTable[i].resources[j] = NullResource;
- }
- return TRUE;
- }
- static int
- Hash(int client, register XID id)
- {
- id &= RESOURCE_ID_MASK;
- switch (clientTable[client].hashsize) {
- case 6:
- return ((int) (0x03F & (id ^ (id >> 6) ^ (id >> 12))));
- case 7:
- return ((int) (0x07F & (id ^ (id >> 7) ^ (id >> 13))));
- case 8:
- return ((int) (0x0FF & (id ^ (id >> 8) ^ (id >> 16))));
- case 9:
- return ((int) (0x1FF & (id ^ (id >> 9))));
- case 10:
- return ((int) (0x3FF & (id ^ (id >> 10))));
- case 11:
- return ((int) (0x7FF & (id ^ (id >> 11))));
- }
- return -1;
- }
- static XID
- AvailableID(register int client,
- register XID id, register XID maxid, register XID goodid)
- {
- ResourcePtr res;
- if ((goodid >= id) && (goodid <= maxid))
- return goodid;
- for (; id <= maxid; id++) {
- res = clientTable[client].resources[Hash(client, id)];
- while (res && (res->id != id))
- res = res->next;
- if (!res)
- return id;
- }
- return 0;
- }
- _X_EXPORT void
- GetXIDRange(int client, Bool server, XID *minp, XID *maxp)
- {
- XID id, maxid;
- ResourcePtr *resp;
- ResourcePtr res;
- int i;
- XID goodid;
- id = (Mask) client << CLIENTOFFSET;
- if (server)
- id |= client ? SERVER_BIT : SERVER_MINID;
- maxid = id | RESOURCE_ID_MASK;
- goodid = 0;
- for (resp = clientTable[client].resources, i = clientTable[client].buckets;
- --i >= 0;) {
- for (res = *resp++; res; res = res->next) {
- if ((res->id < id) || (res->id > maxid))
- continue;
- if (((res->id - id) >= (maxid - res->id)) ?
- (goodid = AvailableID(client, id, res->id - 1, goodid)) :
- !(goodid = AvailableID(client, res->id + 1, maxid, goodid)))
- maxid = res->id - 1;
- else
- id = res->id + 1;
- }
- }
- if (id > maxid)
- id = maxid = 0;
- *minp = id;
- *maxp = maxid;
- }
- /**
- * GetXIDList is called by the XC-MISC extension's MiscGetXIDList function.
- * This function tries to find count unused XIDs for the given client. It
- * puts the IDs in the array pids and returns the number found, which should
- * almost always be the number requested.
- *
- * The circumstances that lead to a call to this function are very rare.
- * Xlib must run out of IDs while trying to generate a request that wants
- * multiple ID's, like the Multi-buffering CreateImageBuffers request.
- *
- * No rocket science in the implementation; just iterate over all
- * possible IDs for the given client and pick the first count IDs
- * that aren't in use. A more efficient algorithm could probably be
- * invented, but this will be used so rarely that this should suffice.
- */
- _X_EXPORT unsigned int
- GetXIDList(ClientPtr pClient, unsigned count, XID *pids)
- {
- unsigned int found = 0;
- XID id = pClient->clientAsMask;
- XID maxid;
- maxid = id | RESOURCE_ID_MASK;
- while ((found < count) && (id <= maxid)) {
- if (!LookupIDByClass(id, RC_ANY)) {
- pids[found++] = id;
- }
- id++;
- }
- return found;
- }
- /*
- * Return the next usable fake client ID.
- *
- * Normally this is just the next one in line, but if we've used the last
- * in the range, we need to find a new range of safe IDs to avoid
- * over-running another client.
- */
- _X_EXPORT XID
- FakeClientID(register int client)
- {
- XID id, maxid;
- id = clientTable[client].fakeID++;
- if (id != clientTable[client].endFakeID)
- return id;
- GetXIDRange(client, TRUE, &id, &maxid);
- if (!id) {
- if (!client)
- FatalError("FakeClientID: server internal ids exhausted\n");
- MarkClientException(clients[client]);
- id = ((Mask) client << CLIENTOFFSET) | (SERVER_BIT * 3);
- maxid = id | RESOURCE_ID_MASK;
- }
- clientTable[client].fakeID = id + 1;
- clientTable[client].endFakeID = maxid + 1;
- return id;
- }
- _X_EXPORT Bool
- AddResource(XID id, RESTYPE type, pointer value)
- {
- int client;
- ClientResourceRec *rrec;
- ResourcePtr res, *head;
- client = CLIENT_ID(id);
- rrec = &clientTable[client];
- if (!rrec->buckets) {
- ErrorF("AddResource(%lx, %lx, %lx), client=%d \n",
- (unsigned long) id, type, (unsigned long) value, client);
- FatalError("client not in use\n");
- }
- if ((rrec->elements >= 4 * rrec->buckets) && (rrec->hashsize < MAXHASHSIZE))
- RebuildTable(client);
- head = &rrec->resources[Hash(client, id)];
- res = malloc(sizeof(ResourceRec));
- if (!res) {
- (*DeleteFuncs[type & TypeMask]) (value, id);
- return FALSE;
- }
- res->next = *head;
- res->id = id;
- res->type = type;
- res->value = value;
- *head = res;
- rrec->elements++;
- if (!(id & SERVER_BIT) && (id >= rrec->expectID))
- rrec->expectID = id + 1;
- return TRUE;
- }
- static void
- RebuildTable(int client)
- {
- int j;
- ResourcePtr res, next;
- ResourcePtr **tails, *resources;
- ResourcePtr **tptr, *rptr;
- /*
- * For now, preserve insertion order, since some ddx layers depend
- * on resources being free in the opposite order they are added.
- */
- j = 2 * clientTable[client].buckets;
- tails = (ResourcePtr **) ALLOCATE_LOCAL(j * sizeof(ResourcePtr *));
- if (!tails)
- return;
- resources = malloc(j * sizeof(ResourcePtr));
- if (!resources) {
- DEALLOCATE_LOCAL(tails);
- return;
- }
- for (rptr = resources, tptr = tails; --j >= 0; rptr++, tptr++) {
- *rptr = NullResource;
- *tptr = rptr;
- }
- clientTable[client].hashsize++;
- for (j = clientTable[client].buckets,
- rptr = clientTable[client].resources; --j >= 0; rptr++) {
- for (res = *rptr; res; res = next) {
- next = res->next;
- res->next = NullResource;
- tptr = &tails[Hash(client, res->id)];
- **tptr = res;
- *tptr = &res->next;
- }
- }
- DEALLOCATE_LOCAL(tails);
- clientTable[client].buckets *= 2;
- free(clientTable[client].resources);
- clientTable[client].resources = resources;
- }
- _X_EXPORT void
- FreeResource(XID id, RESTYPE skipDeleteFuncType)
- {
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- int *eltptr;
- int elements;
- Bool gotOne = FALSE;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- head = &clientTable[cid].resources[Hash(cid, id)];
- eltptr = &clientTable[cid].elements;
- prev = head;
- while ((res = *prev)) {
- if (res->id == id) {
- RESTYPE rtype = res->type;
- *prev = res->next;
- elements = --*eltptr;
- if (rtype & RC_CACHED)
- FlushClientCaches(res->id);
- if (rtype != skipDeleteFuncType)
- (*DeleteFuncs[rtype & TypeMask]) (res->value, res->id);
- free(res);
- if (*eltptr != elements)
- prev = head; /* prev may no longer be valid */
- gotOne = TRUE;
- }
- else
- prev = &res->next;
- }
- if (clients[cid] && (id == clients[cid]->lastDrawableID)) {
- clients[cid]->lastDrawable = (DrawablePtr) WindowTable[0];
- clients[cid]->lastDrawableID = WindowTable[0]->drawable.id;
- }
- }
- if (!gotOne)
- ErrorF("Freeing resource id=%lX which isn't there.\n",
- (unsigned long) id);
- }
- _X_EXPORT void
- FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
- {
- int cid;
- ResourcePtr res;
- ResourcePtr *prev, *head;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- head = &clientTable[cid].resources[Hash(cid, id)];
- prev = head;
- while ((res = *prev)) {
- if (res->id == id && res->type == type) {
- *prev = res->next;
- if (type & RC_CACHED)
- FlushClientCaches(res->id);
- if (!skipFree)
- (*DeleteFuncs[type & TypeMask]) (res->value, res->id);
- free(res);
- break;
- }
- else
- prev = &res->next;
- }
- if (clients[cid] && (id == clients[cid]->lastDrawableID)) {
- clients[cid]->lastDrawable = (DrawablePtr) WindowTable[0];
- clients[cid]->lastDrawableID = WindowTable[0]->drawable.id;
- }
- }
- }
- /*
- * Change the value associated with a resource id. Caller
- * is responsible for "doing the right thing" with the old
- * data
- */
- _X_EXPORT Bool
- ChangeResourceValue(XID id, RESTYPE rtype, pointer value)
- {
- int cid;
- ResourcePtr res;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
- for (; res; res = res->next)
- if ((res->id == id) && (res->type == rtype)) {
- if (rtype & RC_CACHED)
- FlushClientCaches(res->id);
- res->value = value;
- return TRUE;
- }
- }
- return FALSE;
- }
- /* Note: if func adds or deletes resources, then func can get called
- * more than once for some resources. If func adds new resources,
- * func might or might not get called for them. func cannot both
- * add and delete an equal number of resources!
- */
- _X_EXPORT void
- FindClientResourcesByType(ClientPtr client,
- RESTYPE type, FindResType func, pointer cdata)
- {
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
- if (!client)
- client = serverClient;
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++) {
- for (this = resources[i]; this; this = next) {
- next = this->next;
- if (!type || this->type == type) {
- elements = *eltptr;
- (*func) (this->value, this->id, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
- }
- }
- _X_EXPORT void
- FindAllClientResources(ClientPtr client, FindAllRes func, pointer cdata)
- {
- ResourcePtr *resources;
- ResourcePtr this, next;
- int i, elements;
- int *eltptr;
- if (!client)
- client = serverClient;
- resources = clientTable[client->index].resources;
- eltptr = &clientTable[client->index].elements;
- for (i = 0; i < clientTable[client->index].buckets; i++) {
- for (this = resources[i]; this; this = next) {
- next = this->next;
- elements = *eltptr;
- (*func) (this->value, this->id, this->type, cdata);
- if (*eltptr != elements)
- next = resources[i]; /* start over */
- }
- }
- }
- pointer
- LookupClientResourceComplex(ClientPtr client,
- RESTYPE type,
- FindComplexResType func, pointer cdata)
- {
- ResourcePtr *resources;
- ResourcePtr this;
- int i;
- if (!client)
- client = serverClient;
- resources = clientTable[client->index].resources;
- for (i = 0; i < clientTable[client->index].buckets; i++) {
- for (this = resources[i]; this; this = this->next) {
- if (!type || this->type == type) {
- if ((*func) (this->value, this->id, cdata))
- return this->value;
- }
- }
- }
- return NULL;
- }
- void
- FreeClientNeverRetainResources(ClientPtr client)
- {
- ResourcePtr *resources;
- ResourcePtr this;
- ResourcePtr *prev;
- int j;
- if (!client)
- return;
- resources = clientTable[client->index].resources;
- for (j = 0; j < clientTable[client->index].buckets; j++) {
- prev = &resources[j];
- while ((this = *prev)) {
- RESTYPE rtype = this->type;
- if (rtype & RC_NEVERRETAIN) {
- *prev = this->next;
- if (rtype & RC_CACHED)
- FlushClientCaches(this->id);
- (*DeleteFuncs[rtype & TypeMask]) (this->value, this->id);
- free(this);
- }
- else
- prev = &this->next;
- }
- }
- }
- void
- FreeClientResources(ClientPtr client)
- {
- ResourcePtr *resources;
- ResourcePtr this;
- int j;
- /* This routine shouldn't be called with a null client, but just in
- case ... */
- if (!client)
- return;
- HandleSaveSet(client);
- resources = clientTable[client->index].resources;
- for (j = 0; j < clientTable[client->index].buckets; j++) {
- /* It may seem silly to update the head of this resource list as
- we delete the members, since the entire list will be deleted any way,
- but there are some resource deletion functions "FreeClientPixels" for
- one which do a LookupID on another resource id (a Colormap id in this
- case), so the resource list must be kept valid up to the point that
- it is deleted, so every time we delete a resource, we must update the
- head, just like in FreeResource. I hope that this doesn't slow down
- mass deletion appreciably. PRH */
- ResourcePtr *head;
- head = &resources[j];
- for (this = *head; this; this = *head) {
- RESTYPE rtype = this->type;
- *head = this->next;
- if (rtype & RC_CACHED)
- FlushClientCaches(this->id);
- (*DeleteFuncs[rtype & TypeMask]) (this->value, this->id);
- free(this);
- }
- }
- free(clientTable[client->index].resources);
- clientTable[client->index].resources = NULL;
- clientTable[client->index].buckets = 0;
- }
- void
- FreeAllResources()
- {
- int i;
- for (i = currentMaxClients; --i >= 0;) {
- if (clientTable[i].buckets)
- FreeClientResources(clients[i]);
- }
- }
- _X_EXPORT Bool
- LegalNewID(XID id, register ClientPtr client)
- {
- return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) &&
- ((clientTable[client->index].expectID <= id) ||
- !LookupIDByClass(id, RC_ANY)));
- }
- /* SecurityLookupIDByType and SecurityLookupIDByClass:
- * These are the heart of the resource ID security system. They take
- * two additional arguments compared to the old LookupID functions:
- * the client doing the lookup, and the access mode (see resource.h).
- * The resource is returned if it exists and the client is allowed access,
- * else NULL is returned.
- */
- _X_EXPORT pointer
- SecurityLookupIDByType(ClientPtr client, XID id, RESTYPE rtype, Mask mode)
- {
- int cid;
- ResourcePtr res;
- pointer retval = NULL;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
- for (; res; res = res->next)
- if ((res->id == id) && (res->type == rtype)) {
- retval = res->value;
- break;
- }
- }
- return retval;
- }
- _X_EXPORT pointer
- SecurityLookupIDByClass(ClientPtr client, XID id, RESTYPE classes, Mask mode)
- {
- int cid;
- ResourcePtr res = NULL;
- pointer retval = NULL;
- if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
- res = clientTable[cid].resources[Hash(cid, id)];
- for (; res; res = res->next)
- if ((res->id == id) && (res->type & classes)) {
- retval = res->value;
- break;
- }
- }
- return retval;
- }
- /* We can't replace the LookupIDByType and LookupIDByClass functions with
- * macros because of compatibility with loadable servers.
- */
- _X_EXPORT pointer
- LookupIDByType(XID id, RESTYPE rtype)
- {
- return SecurityLookupIDByType(NullClient, id, rtype, SecurityUnknownAccess);
- }
- _X_EXPORT pointer
- LookupIDByClass(XID id, RESTYPE classes)
- {
- return SecurityLookupIDByClass(NullClient, id, classes,
- SecurityUnknownAccess);
- }
|