📄 resource.c
字号:
resources = (ResourcePtr *)xalloc(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; xfree(clientTable[client].resources); clientTable[client].resources = resources;}voidFreeResource(id, skipDeleteFuncType) XID id; RESTYPE skipDeleteFuncType;{ int cid; register ResourcePtr res; register ResourcePtr *prev, *head; register 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); xfree(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) FatalError("Freeing resource id=%X which isn't there", id);}voidFreeResourceByType(id, type, skipFree) XID id; RESTYPE type; Bool skipFree;{ int cid; register ResourcePtr res; register 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); xfree(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 */BoolChangeResourceValue (id, rtype, value) XID id; RESTYPE rtype; pointer value;{ int cid; register 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! */voidFindClientResourcesByType(client, type, func, cdata) ClientPtr client; RESTYPE type; FindResType func; pointer cdata;{ register ResourcePtr *resources; register ResourcePtr this, next; int i, elements; register 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 */ } } }}voidFreeClientNeverRetainResources(client) 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); xfree(this); } else prev = &this->next; } }}voidFreeClientResources(client) ClientPtr client;{ register ResourcePtr *resources; register 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); xfree(this); } } xfree(clientTable[client->index].resources); clientTable[client->index].buckets = 0;}voidFreeAllResources(){ int i; for (i = currentMaxClients; --i >= 0; ) { if (clientTable[i].buckets) FreeClientResources(clients[i]); }}BoolLegalNewID(id, client) XID id; register ClientPtr client;{ return ((client->clientAsMask == (id & ~RESOURCE_ID_MASK)) && ((clientTable[client->index].expectID <= id) || !LookupIDByClass(id, RC_ANY)));}#ifdef XCSECURITY/* 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. */pointerSecurityLookupIDByType(client, id, rtype, mode) ClientPtr client; XID id; RESTYPE rtype; Mask mode;{ int cid; register ResourcePtr res; pointer retval = NULL; assert(client == NullClient || (client->index <= currentMaxClients && clients[client->index] == client)); assert( (rtype & TypeMask) <= lastResourceType); 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; } } if (retval && client && client->CheckAccess) retval = (* client->CheckAccess)(client, id, rtype, mode, retval); return retval;}pointerSecurityLookupIDByClass(client, id, classes, mode) ClientPtr client; XID id; RESTYPE classes; Mask mode;{ int cid; register ResourcePtr res; pointer retval = NULL; assert(client == NullClient || (client->index <= currentMaxClients && clients[client->index] == client)); assert (classes >= lastResourceClass); 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; } } if (retval && client && client->CheckAccess) retval = (* client->CheckAccess)(client, id, classes, mode, retval); return retval;}/* We can't replace the LookupIDByType and LookupIDByClass functions with * macros because of compatibility with loadable servers. */pointerLookupIDByType(id, rtype) XID id; RESTYPE rtype;{ return SecurityLookupIDByType(NullClient, id, rtype, SecurityUnknownAccess);}pointerLookupIDByClass(id, classes) XID id; RESTYPE classes;{ return SecurityLookupIDByClass(NullClient, id, classes, SecurityUnknownAccess);}#else /* not XCSECURITY *//* * LookupIDByType returns the object with the given id and type, else NULL. */ pointerLookupIDByType(id, rtype) XID id; RESTYPE rtype;{ int cid; register 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)) return res->value; } return (pointer)NULL;}/* * LookupIDByClass returns the object with the given id and any one of the * given classes, else NULL. */ pointerLookupIDByClass(id, classes) XID id; RESTYPE classes;{ int cid; register 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 & classes)) return res->value; } return (pointer)NULL;}#endif /* XCSECURITY */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -