1 /*
2 
3 Copyright 1993, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26 
27 */
28 /*
29  * Copyright © 2010, Keith Packard
30  * Copyright © 2010, Jamey Sharp
31  *
32  * Permission to use, copy, modify, distribute, and sell this software and its
33  * documentation for any purpose is hereby granted without fee, provided that
34  * the above copyright notice appear in all copies and that both that copyright
35  * notice and this permission notice appear in supporting documentation, and
36  * that the name of the copyright holders not be used in advertising or
37  * publicity pertaining to distribution of the software without specific,
38  * written prior permission.  The copyright holders make no representations
39  * about the suitability of this software for any purpose.  It is provided "as
40  * is" without express or implied warranty.
41  *
42  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
44  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
45  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
46  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
47  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
48  * OF THIS SOFTWARE.
49  */
50 
51 #ifdef HAVE_DIX_CONFIG_H
52 #include <dix-config.h>
53 #endif
54 
55 #include <stddef.h>
56 #include "windowstr.h"
57 #include "resource.h"
58 #include "privates.h"
59 #include "gcstruct.h"
60 #include "cursorstr.h"
61 #include "colormapst.h"
62 #include "inputstr.h"
63 #include "scrnintstr.h"
64 #include "extnsionst.h"
65 #include "inputstr.h"
66 
67 static DevPrivateSetRec global_keys[PRIVATE_LAST];
68 
69 static const Bool xselinux_private[PRIVATE_LAST] = {
70     [PRIVATE_SCREEN] = TRUE,
71     [PRIVATE_CLIENT] = TRUE,
72     [PRIVATE_WINDOW] = TRUE,
73     [PRIVATE_PIXMAP] = TRUE,
74     [PRIVATE_GC] = TRUE,
75     [PRIVATE_CURSOR] = TRUE,
76     [PRIVATE_COLORMAP] = TRUE,
77     [PRIVATE_DEVICE] = TRUE,
78     [PRIVATE_EXTENSION] = TRUE,
79     [PRIVATE_SELECTION] = TRUE,
80     [PRIVATE_PROPERTY] = TRUE,
81     [PRIVATE_PICTURE] = TRUE,
82     [PRIVATE_GLYPHSET] = TRUE,
83 };
84 
85 static const char *key_names[PRIVATE_LAST] = {
86     /* XSELinux uses the same private keys for numerous objects */
87     [PRIVATE_XSELINUX] = "XSELINUX",
88 
89     /* Otherwise, you get a private in just the requested structure
90      */
91     /* These can have objects created before all of the keys are registered */
92     [PRIVATE_SCREEN] = "SCREEN",
93     [PRIVATE_EXTENSION] = "EXTENSION",
94     [PRIVATE_COLORMAP] = "COLORMAP",
95     [PRIVATE_DEVICE] = "DEVICE",
96 
97     /* These cannot have any objects before all relevant keys are registered */
98     [PRIVATE_CLIENT] = "CLIENT",
99     [PRIVATE_PROPERTY] = "PROPERTY",
100     [PRIVATE_SELECTION] = "SELECTION",
101     [PRIVATE_WINDOW] = "WINDOW",
102     [PRIVATE_PIXMAP] = "PIXMAP",
103     [PRIVATE_GC] = "GC",
104     [PRIVATE_CURSOR] = "CURSOR",
105     [PRIVATE_CURSOR_BITS] = "CURSOR_BITS",
106 
107     /* extension privates */
108     [PRIVATE_GLYPH] = "GLYPH",
109     [PRIVATE_GLYPHSET] = "GLYPHSET",
110     [PRIVATE_PICTURE] = "PICTURE",
111     [PRIVATE_SYNC_FENCE] = "SYNC_FENCE",
112 };
113 
114 static const Bool screen_specific_private[PRIVATE_LAST] = {
115     [PRIVATE_SCREEN] = FALSE,
116     [PRIVATE_CLIENT] = FALSE,
117     [PRIVATE_WINDOW] = TRUE,
118     [PRIVATE_PIXMAP] = TRUE,
119     [PRIVATE_GC] = TRUE,
120     [PRIVATE_CURSOR] = FALSE,
121     [PRIVATE_COLORMAP] = FALSE,
122     [PRIVATE_DEVICE] = FALSE,
123     [PRIVATE_EXTENSION] = FALSE,
124     [PRIVATE_SELECTION] = FALSE,
125     [PRIVATE_PROPERTY] = FALSE,
126     [PRIVATE_PICTURE] = TRUE,
127     [PRIVATE_GLYPHSET] = FALSE,
128 };
129 
130 typedef Bool (*FixupFunc) (PrivatePtr *privates, int offset, unsigned bytes);
131 
132 typedef enum { FixupMove, FixupRealloc } FixupType;
133 
134 static Bool
dixReallocPrivates(PrivatePtr * privates,int old_offset,unsigned bytes)135 dixReallocPrivates(PrivatePtr *privates, int old_offset, unsigned bytes)
136 {
137     void *new_privates;
138 
139     new_privates = realloc(*privates, old_offset + bytes);
140     if (!new_privates)
141         return FALSE;
142     memset((char *) new_privates + old_offset, '\0', bytes);
143     *privates = new_privates;
144     return TRUE;
145 }
146 
147 static Bool
dixMovePrivates(PrivatePtr * privates,int new_offset,unsigned bytes)148 dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
149 {
150     memmove((char *) *privates + bytes, *privates, new_offset - bytes);
151     memset(*privates, '\0', bytes);
152     return TRUE;
153 }
154 
155 static Bool
fixupOneScreen(ScreenPtr pScreen,FixupFunc fixup,unsigned bytes)156 fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
157 {
158     intptr_t        dist;
159     char            *old;
160     char            *new;
161     DevPrivateKey   *keyp, key;
162     DevPrivateType  type;
163     int             size;
164 
165     old = (char *) pScreen->devPrivates;
166     size = global_keys[PRIVATE_SCREEN].offset;
167     if (!fixup (&pScreen->devPrivates, size, bytes))
168         return FALSE;
169 
170     /* Screen privates can contain screen-specific private keys
171      * for other types. When they move, the linked list we use to
172      * track them gets scrambled. Fix that by computing the change
173      * in the location of each private adjusting our linked list
174      * pointers to match
175      */
176 
177     new = (char *) pScreen->devPrivates;
178 
179     /* Moving means everyone shifts up in the privates by 'bytes' amount,
180      * realloc means the base pointer moves
181      */
182     if (fixup == dixMovePrivates)
183         new += bytes;
184 
185     dist = new - old;
186 
187     if (dist) {
188         for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
189 
190             /* Walk the privates list, being careful as the
191              * pointers are scrambled before we patch them.
192              */
193             for (keyp = &pScreen->screenSpecificPrivates[type].key;
194                  (key = *keyp) != NULL;
195                  keyp = &key->next)
196             {
197 
198                 /* Only mangle things if the private structure
199                  * is contained within the allocation. Privates
200                  * stored elsewhere will be left alone
201                  */
202                 if (old <= (char *) key && (char *) key < old + size)
203                 {
204                     /* Compute new location of key */
205                     key = (DevPrivateKey) ((char *) key + dist);
206 
207                     /* Patch the list */
208                     *keyp = key;
209                 }
210             }
211     }
212     return TRUE;
213 }
214 
215 static Bool
fixupScreens(FixupFunc fixup,unsigned bytes)216 fixupScreens(FixupFunc fixup, unsigned bytes)
217 {
218     int s;
219 
220     for (s = 0; s < screenInfo.numScreens; s++)
221         if (!fixupOneScreen (screenInfo.screens[s], fixup, bytes))
222             return FALSE;
223 
224     for (s = 0; s < screenInfo.numGPUScreens; s++)
225         if (!fixupOneScreen (screenInfo.gpuscreens[s], fixup, bytes))
226             return FALSE;
227     return TRUE;
228 }
229 
230 static Bool
fixupServerClient(FixupFunc fixup,unsigned bytes)231 fixupServerClient(FixupFunc fixup, unsigned bytes)
232 {
233     if (serverClient)
234         return fixup(&serverClient->devPrivates, global_keys[PRIVATE_CLIENT].offset,
235                      bytes);
236     return TRUE;
237 }
238 
239 static Bool
fixupExtensions(FixupFunc fixup,unsigned bytes)240 fixupExtensions(FixupFunc fixup, unsigned bytes)
241 {
242     unsigned char major;
243     ExtensionEntry *extension;
244 
245     for (major = EXTENSION_BASE; (extension = GetExtensionEntry(major));
246          major++)
247         if (!fixup
248             (&extension->devPrivates, global_keys[PRIVATE_EXTENSION].offset, bytes))
249             return FALSE;
250     return TRUE;
251 }
252 
253 static Bool
fixupDefaultColormaps(FixupFunc fixup,unsigned bytes)254 fixupDefaultColormaps(FixupFunc fixup, unsigned bytes)
255 {
256     int s;
257 
258     for (s = 0; s < screenInfo.numScreens; s++) {
259         ColormapPtr cmap;
260 
261         dixLookupResourceByType((void **) &cmap,
262                                 screenInfo.screens[s]->defColormap, RT_COLORMAP,
263                                 serverClient, DixCreateAccess);
264         if (cmap &&
265             !fixup(&cmap->devPrivates, screenInfo.screens[s]->screenSpecificPrivates[PRIVATE_COLORMAP].offset, bytes))
266             return FALSE;
267     }
268     return TRUE;
269 }
270 
271 static Bool
fixupDeviceList(DeviceIntPtr device,FixupFunc fixup,unsigned bytes)272 fixupDeviceList(DeviceIntPtr device, FixupFunc fixup, unsigned bytes)
273 {
274     while (device) {
275         if (!fixup(&device->devPrivates, global_keys[PRIVATE_DEVICE].offset, bytes))
276             return FALSE;
277         device = device->next;
278     }
279     return TRUE;
280 }
281 
282 static Bool
fixupDevices(FixupFunc fixup,unsigned bytes)283 fixupDevices(FixupFunc fixup, unsigned bytes)
284 {
285     return (fixupDeviceList(inputInfo.devices, fixup, bytes) &&
286             fixupDeviceList(inputInfo.off_devices, fixup, bytes));
287 }
288 
289 static Bool (*const allocated_early[PRIVATE_LAST]) (FixupFunc, unsigned) = {
290     [PRIVATE_SCREEN] = fixupScreens,
291     [PRIVATE_CLIENT] = fixupServerClient,
292     [PRIVATE_EXTENSION] = fixupExtensions,
293     [PRIVATE_COLORMAP] = fixupDefaultColormaps,
294     [PRIVATE_DEVICE] = fixupDevices,
295 };
296 
297 static void
grow_private_set(DevPrivateSetPtr set,unsigned bytes)298 grow_private_set(DevPrivateSetPtr set, unsigned bytes)
299 {
300     DevPrivateKey       k;
301 
302     for (k = set->key; k; k = k->next)
303         k->offset += bytes;
304     set->offset += bytes;
305 }
306 
307 static void
grow_screen_specific_set(DevPrivateType type,unsigned bytes)308 grow_screen_specific_set(DevPrivateType type, unsigned bytes)
309 {
310     int s;
311 
312     /* Update offsets for all screen-specific keys */
313     for (s = 0; s < screenInfo.numScreens; s++) {
314         ScreenPtr       pScreen = screenInfo.screens[s];
315 
316         grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
317     }
318     for (s = 0; s < screenInfo.numGPUScreens; s++) {
319         ScreenPtr       pScreen = screenInfo.gpuscreens[s];
320 
321         grow_private_set(&pScreen->screenSpecificPrivates[type], bytes);
322     }
323 }
324 
325 /*
326  * Register a private key. This takes the type of object the key will
327  * be used with, which may be PRIVATE_ALL indicating that this key
328  * will be used with all of the private objects. If 'size' is
329  * non-zero, then the specified amount of space will be allocated in
330  * the private storage. Otherwise, space for a single pointer will
331  * be allocated which can be set with dixSetPrivate
332  */
333 Bool
dixRegisterPrivateKey(DevPrivateKey key,DevPrivateType type,unsigned size)334 dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size)
335 {
336     DevPrivateType t;
337     int offset;
338     unsigned bytes;
339 
340     if (key->initialized) {
341         assert(size == key->size);
342         return TRUE;
343     }
344 
345     /* Compute required space */
346     bytes = size;
347     if (size == 0)
348         bytes = sizeof(void *);
349 
350     /* align to pointer size */
351     bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
352 
353     /* Update offsets for all affected keys */
354     if (type == PRIVATE_XSELINUX) {
355 
356         /* Resize if we can, or make sure nothing's allocated if we can't
357          */
358         for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
359             if (xselinux_private[t]) {
360                 if (!allocated_early[t])
361                     assert(!global_keys[t].created);
362                 else if (!allocated_early[t] (dixReallocPrivates, bytes))
363                     return FALSE;
364             }
365 
366         /* Move all existing keys up in the privates space to make
367          * room for this new global key
368          */
369         for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
370             if (xselinux_private[t]) {
371                 grow_private_set(&global_keys[t], bytes);
372                 grow_screen_specific_set(t, bytes);
373                 if (allocated_early[t])
374                     allocated_early[t] (dixMovePrivates, bytes);
375             }
376 
377         }
378 
379         offset = 0;
380     }
381     else {
382         /* Resize if we can, or make sure nothing's allocated if we can't */
383         if (!allocated_early[type])
384             assert(!global_keys[type].created);
385         else if (!allocated_early[type] (dixReallocPrivates, bytes))
386             return FALSE;
387         offset = global_keys[type].offset;
388         global_keys[type].offset += bytes;
389         grow_screen_specific_set(type, bytes);
390     }
391 
392     /* Setup this key */
393     key->offset = offset;
394     key->size = size;
395     key->initialized = TRUE;
396     key->type = type;
397     key->allocated = FALSE;
398     key->next = global_keys[type].key;
399     global_keys[type].key = key;
400 
401     return TRUE;
402 }
403 
404 Bool
dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey,ScreenPtr pScreen,DevPrivateType type,unsigned size)405 dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
406                             DevPrivateType type, unsigned size)
407 {
408     DevPrivateKey key;
409 
410     if (!dixRegisterPrivateKey(&screenKey->screenKey, PRIVATE_SCREEN, 0))
411         return FALSE;
412     key = dixGetPrivate(&pScreen->devPrivates, &screenKey->screenKey);
413     if (key != NULL) {
414         assert(key->size == size);
415         assert(key->type == type);
416         return TRUE;
417     }
418     key = calloc(sizeof(DevPrivateKeyRec), 1);
419     if (!key)
420         return FALSE;
421     if (!dixRegisterPrivateKey(key, type, size)) {
422         free(key);
423         return FALSE;
424     }
425     key->allocated = TRUE;
426     dixSetPrivate(&pScreen->devPrivates, &screenKey->screenKey, key);
427     return TRUE;
428 }
429 
430 DevPrivateKey
_dixGetScreenPrivateKey(const DevScreenPrivateKey key,ScreenPtr pScreen)431 _dixGetScreenPrivateKey(const DevScreenPrivateKey key, ScreenPtr pScreen)
432 {
433     return dixGetPrivate(&pScreen->devPrivates, &key->screenKey);
434 }
435 
436 /*
437  * Initialize privates by zeroing them
438  */
439 void
_dixInitPrivates(PrivatePtr * privates,void * addr,DevPrivateType type)440 _dixInitPrivates(PrivatePtr *privates, void *addr, DevPrivateType type)
441 {
442     assert (!screen_specific_private[type]);
443 
444     global_keys[type].created++;
445     if (xselinux_private[type])
446         global_keys[PRIVATE_XSELINUX].created++;
447     if (global_keys[type].offset == 0)
448         addr = 0;
449     *privates = addr;
450     memset(addr, '\0', global_keys[type].offset);
451 }
452 
453 /*
454  * Clean up privates
455  */
456 void
_dixFiniPrivates(PrivatePtr privates,DevPrivateType type)457 _dixFiniPrivates(PrivatePtr privates, DevPrivateType type)
458 {
459     global_keys[type].created--;
460     if (xselinux_private[type])
461         global_keys[PRIVATE_XSELINUX].created--;
462 }
463 
464 /*
465  * Allocate new object with privates.
466  *
467  * This is expected to be invoked from the
468  * dixAllocateObjectWithPrivates macro
469  */
470 void *
_dixAllocateObjectWithPrivates(unsigned baseSize,unsigned clear,unsigned offset,DevPrivateType type)471 _dixAllocateObjectWithPrivates(unsigned baseSize, unsigned clear,
472                                unsigned offset, DevPrivateType type)
473 {
474     unsigned totalSize;
475     void *object;
476     PrivatePtr privates;
477     PrivatePtr *devPrivates;
478 
479     assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
480     assert(!screen_specific_private[type]);
481 
482     /* round up so that void * is aligned */
483     baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
484     totalSize = baseSize + global_keys[type].offset;
485     object = malloc(totalSize);
486     if (!object)
487         return NULL;
488 
489     memset(object, '\0', clear);
490     privates = (PrivatePtr) (((char *) object) + baseSize);
491     devPrivates = (PrivatePtr *) ((char *) object + offset);
492 
493     _dixInitPrivates(devPrivates, privates, type);
494 
495     return object;
496 }
497 
498 /*
499  * Allocate privates separately from containing object.
500  * Used for clients and screens.
501  */
502 Bool
dixAllocatePrivates(PrivatePtr * privates,DevPrivateType type)503 dixAllocatePrivates(PrivatePtr *privates, DevPrivateType type)
504 {
505     unsigned size;
506     PrivatePtr p;
507 
508     assert(type > PRIVATE_XSELINUX && type < PRIVATE_LAST);
509     assert(!screen_specific_private[type]);
510 
511     size = global_keys[type].offset;
512     if (!size) {
513         p = NULL;
514     }
515     else {
516         if (!(p = malloc(size)))
517             return FALSE;
518     }
519 
520     _dixInitPrivates(privates, p, type);
521     ++global_keys[type].allocated;
522 
523     return TRUE;
524 }
525 
526 /*
527  * Free an object that has privates
528  *
529  * This is expected to be invoked from the
530  * dixFreeObjectWithPrivates macro
531  */
532 void
_dixFreeObjectWithPrivates(void * object,PrivatePtr privates,DevPrivateType type)533 _dixFreeObjectWithPrivates(void *object, PrivatePtr privates,
534                            DevPrivateType type)
535 {
536     _dixFiniPrivates(privates, type);
537     free(object);
538 }
539 
540 /*
541  * Called to free screen or client privates
542  */
543 void
dixFreePrivates(PrivatePtr privates,DevPrivateType type)544 dixFreePrivates(PrivatePtr privates, DevPrivateType type)
545 {
546     _dixFiniPrivates(privates, type);
547     --global_keys[type].allocated;
548     free(privates);
549 }
550 
551 /*
552  * Return size of privates for the specified type
553  */
554 extern _X_EXPORT int
dixPrivatesSize(DevPrivateType type)555 dixPrivatesSize(DevPrivateType type)
556 {
557     assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
558     assert (!screen_specific_private[type]);
559 
560     return global_keys[type].offset;
561 }
562 
563 /* Table of devPrivates offsets */
564 static const int offsets[] = {
565     -1,                         /* RT_NONE */
566     offsetof(WindowRec, devPrivates),   /* RT_WINDOW */
567     offsetof(PixmapRec, devPrivates),   /* RT_PIXMAP */
568     offsetof(GC, devPrivates),  /* RT_GC */
569     -1,                         /* RT_FONT */
570     offsetof(CursorRec, devPrivates),   /* RT_CURSOR */
571     offsetof(ColormapRec, devPrivates), /* RT_COLORMAP */
572 };
573 
574 int
dixLookupPrivateOffset(RESTYPE type)575 dixLookupPrivateOffset(RESTYPE type)
576 {
577     /*
578      * Special kludge for DBE which registers a new resource type that
579      * points at pixmaps (thanks, DBE)
580      */
581     if (type & RC_DRAWABLE) {
582         if (type == RT_WINDOW)
583             return offsets[RT_WINDOW & TypeMask];
584         else
585             return offsets[RT_PIXMAP & TypeMask];
586     }
587     type = type & TypeMask;
588     if (type < ARRAY_SIZE(offsets))
589         return offsets[type];
590     return -1;
591 }
592 
593 /*
594  * Screen-specific privates
595  */
596 
597 extern _X_EXPORT Bool
dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen,DevPrivateKey key,DevPrivateType type,unsigned size)598 dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
599                                     DevPrivateType type, unsigned size)
600 {
601     int offset;
602     unsigned bytes;
603 
604     if (!screen_specific_private[type])
605         FatalError("Attempt to allocate screen-specific private storage for type %s\n",
606                    key_names[type]);
607 
608     if (key->initialized) {
609         assert(size == key->size);
610         return TRUE;
611     }
612 
613     /* Compute required space */
614     bytes = size;
615     if (size == 0)
616         bytes = sizeof(void *);
617 
618     /* align to void * size */
619     bytes = (bytes + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
620 
621     assert (!allocated_early[type]);
622     assert (!pScreen->screenSpecificPrivates[type].created);
623     offset = pScreen->screenSpecificPrivates[type].offset;
624     pScreen->screenSpecificPrivates[type].offset += bytes;
625 
626     /* Setup this key */
627     key->offset = offset;
628     key->size = size;
629     key->initialized = TRUE;
630     key->type = type;
631     key->allocated = FALSE;
632     key->next = pScreen->screenSpecificPrivates[type].key;
633     pScreen->screenSpecificPrivates[type].key = key;
634 
635     return TRUE;
636 }
637 
638 /* Clean up screen-specific privates before CloseScreen */
639 void
dixFreeScreenSpecificPrivates(ScreenPtr pScreen)640 dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
641 {
642     DevPrivateType t;
643 
644     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
645         DevPrivateKey key;
646 
647         for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) {
648             key->initialized = FALSE;
649         }
650     }
651 }
652 
653 /* Initialize screen-specific privates in AddScreen */
654 void
dixInitScreenSpecificPrivates(ScreenPtr pScreen)655 dixInitScreenSpecificPrivates(ScreenPtr pScreen)
656 {
657     DevPrivateType      t;
658 
659     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++)
660         pScreen->screenSpecificPrivates[t].offset = global_keys[t].offset;
661 }
662 
663 /* Initialize screen-specific privates in AddScreen */
664 void
_dixInitScreenPrivates(ScreenPtr pScreen,PrivatePtr * privates,void * addr,DevPrivateType type)665 _dixInitScreenPrivates(ScreenPtr pScreen, PrivatePtr *privates, void *addr, DevPrivateType type)
666 {
667     int privates_size;
668     assert (screen_specific_private[type]);
669 
670     if (pScreen) {
671         privates_size = pScreen->screenSpecificPrivates[type].offset;
672         pScreen->screenSpecificPrivates[type].created++;
673     }
674     else
675         privates_size = global_keys[type].offset;
676 
677     global_keys[type].created++;
678     if (xselinux_private[type])
679         global_keys[PRIVATE_XSELINUX].created++;
680     if (privates_size == 0)
681         addr = 0;
682     *privates = addr;
683     memset(addr, '\0', privates_size);
684 }
685 
686 void *
_dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,unsigned baseSize,unsigned clear,unsigned offset,DevPrivateType type)687 _dixAllocateScreenObjectWithPrivates(ScreenPtr pScreen,
688                                      unsigned baseSize,
689                                      unsigned clear,
690                                      unsigned offset,
691                                      DevPrivateType type)
692 {
693     unsigned totalSize;
694     void *object;
695     PrivatePtr privates;
696     PrivatePtr *devPrivates;
697     int privates_size;
698 
699     assert(type > PRIVATE_SCREEN && type < PRIVATE_LAST);
700     assert (screen_specific_private[type]);
701 
702     if (pScreen)
703         privates_size = pScreen->screenSpecificPrivates[type].offset;
704     else
705         privates_size = global_keys[type].offset;
706     /* round up so that pointer is aligned */
707     baseSize = (baseSize + sizeof(void *) - 1) & ~(sizeof(void *) - 1);
708     totalSize = baseSize + privates_size;
709     object = malloc(totalSize);
710     if (!object)
711         return NULL;
712 
713     memset(object, '\0', clear);
714     privates = (PrivatePtr) (((char *) object) + baseSize);
715     devPrivates = (PrivatePtr *) ((char *) object + offset);
716 
717     _dixInitScreenPrivates(pScreen, devPrivates, privates, type);
718 
719     return object;
720 }
721 
722 int
dixScreenSpecificPrivatesSize(ScreenPtr pScreen,DevPrivateType type)723 dixScreenSpecificPrivatesSize(ScreenPtr pScreen, DevPrivateType type)
724 {
725     assert(type >= PRIVATE_SCREEN && type < PRIVATE_LAST);
726 
727     if (screen_specific_private[type])
728         return pScreen->screenSpecificPrivates[type].offset;
729     else
730         return global_keys[type].offset;
731 }
732 
733 void
dixPrivateUsage(void)734 dixPrivateUsage(void)
735 {
736     int objects = 0;
737     int bytes = 0;
738     int alloc = 0;
739     DevPrivateType t;
740 
741     for (t = PRIVATE_XSELINUX + 1; t < PRIVATE_LAST; t++) {
742         if (global_keys[t].offset) {
743             ErrorF
744                 ("%s: %d objects of %d bytes = %d total bytes %d private allocs\n",
745                  key_names[t], global_keys[t].created, global_keys[t].offset,
746                  global_keys[t].created * global_keys[t].offset, global_keys[t].allocated);
747             bytes += global_keys[t].created * global_keys[t].offset;
748             objects += global_keys[t].created;
749             alloc += global_keys[t].allocated;
750         }
751     }
752     ErrorF("TOTAL: %d objects, %d bytes, %d allocs\n", objects, bytes, alloc);
753 }
754 
755 void
dixResetPrivates(void)756 dixResetPrivates(void)
757 {
758     DevPrivateType t;
759 
760     for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
761         DevPrivateKey key, next;
762 
763         for (key = global_keys[t].key; key; key = next) {
764             next = key->next;
765             key->offset = 0;
766             key->initialized = FALSE;
767             key->size = 0;
768             key->type = 0;
769             if (key->allocated)
770                 free(key);
771         }
772         if (global_keys[t].created) {
773             ErrorF("%d %ss still allocated at reset\n",
774                    global_keys[t].created, key_names[t]);
775             dixPrivateUsage();
776         }
777         global_keys[t].key = NULL;
778         global_keys[t].offset = 0;
779         global_keys[t].created = 0;
780         global_keys[t].allocated = 0;
781     }
782 }
783 
784 Bool
dixPrivatesCreated(DevPrivateType type)785 dixPrivatesCreated(DevPrivateType type)
786 {
787     if (global_keys[type].created)
788         return TRUE;
789     else
790         return FALSE;
791 }
792