]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - lib/libc/gen/aux.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / lib / libc / gen / aux.c
1 /*-
2  * Copyright 2010 Konstantin Belousov <kib@FreeBSD.ORG>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "namespace.h"
31 #include <elf.h>
32 #include <errno.h>
33 #include <link.h>
34 #include <pthread.h>
35 #include <string.h>
36 #include "un-namespace.h"
37 #include "libc_private.h"
38
39 Elf_Auxinfo *__elf_aux_vector;
40
41 static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
42
43 static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
44 static char *canary, *pagesizes;
45
46 static void
47 init_aux(void)
48 {
49         Elf_Auxinfo *aux;
50
51         for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
52                 switch (aux->a_type) {
53                 case AT_CANARY:
54                         canary = (char *)(aux->a_un.a_ptr);
55                         break;
56
57                 case AT_CANARYLEN:
58                         canary_len = aux->a_un.a_val;
59                         break;
60
61                 case AT_PAGESIZES:
62                         pagesizes = (char *)(aux->a_un.a_ptr);
63                         break;
64
65                 case AT_PAGESIZESLEN:
66                         pagesizes_len = aux->a_un.a_val;
67                         break;
68
69                 case AT_PAGESZ:
70                         pagesize = aux->a_un.a_val;
71                         break;
72
73                 case AT_OSRELDATE:
74                         osreldate = aux->a_un.a_val;
75                         break;
76
77                 case AT_NCPUS:
78                         ncpus = aux->a_un.a_val;
79                         break;
80                 }
81         }
82 }
83
84 int
85 _elf_aux_info(int aux, void *buf, int buflen)
86 {
87         int res;
88
89         if (__elf_aux_vector == NULL)
90                 return (ENOSYS);
91         _once(&aux_once, init_aux);
92
93         switch (aux) {
94         case AT_CANARY:
95                 if (canary != NULL && canary_len >= buflen) {
96                         memcpy(buf, canary, buflen);
97                         memset(canary, 0, canary_len);
98                         canary = NULL;
99                         res = 0;
100                 } else
101                         res = ENOENT;
102                 break;
103         case AT_PAGESIZES:
104                 if (pagesizes != NULL && pagesizes_len >= buflen) {
105                         memcpy(buf, pagesizes, buflen);
106                         res = 0;
107                 } else
108                         res = ENOENT;
109                 break;
110
111         case AT_PAGESZ:
112                 if (buflen == sizeof(int)) {
113                         if (pagesize != 0) {
114                                 *(int *)buf = pagesize;
115                                 res = 0;
116                         } else
117                                 res = ENOENT;
118                 } else
119                         res = EINVAL;
120                 break;
121         case AT_OSRELDATE:
122                 if (buflen == sizeof(int)) {
123                         if (osreldate != 0) {
124                                 *(int *)buf = osreldate;
125                                 res = 0;
126                         } else
127                                 res = ENOENT;
128                 } else
129                         res = EINVAL;
130                 break;
131         case AT_NCPUS:
132                 if (buflen == sizeof(int)) {
133                         if (ncpus != 0) {
134                                 *(int *)buf = ncpus;
135                                 res = 0;
136                         } else
137                                 res = ENOENT;
138                 } else
139                         res = EINVAL;
140                 break;
141         default:
142                 res = ENOENT;
143                 break;
144         }
145         return (res);
146 }