2.3.4-2
[glibc.git] / fedora / glibc_post_upgrade.c
blob9111184605f2741cc212a1d6267e8abd16314b87
1 #if defined __sparc__ && defined __arch64__
2 register void *__thread_self __asm ("g7");
3 #endif
4 #include <sys/types.h>
5 #include <sys/wait.h>
6 #include <stdio.h>
7 #include <errno.h>
8 #include <unistd.h>
9 #include <sys/time.h>
10 #include <dirent.h>
11 #include <stddef.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <sys/stat.h>
15 #include <elf.h>
17 #define verbose_exec(failcode, path...) \
18 do \
19 { \
20 char *const arr[] = { path, NULL }; \
21 vexec (failcode, arr); \
22 } while (0)
24 __attribute__((noinline)) void vexec (int failcode, char *const path[]);
25 __attribute__((noinline)) void says (const char *str);
26 __attribute__((noinline)) void sayn (long num);
27 __attribute__((noinline)) void message (char *const path[]);
28 __attribute__((noinline)) int check_elf (const char *name);
30 int
31 main (void)
33 int rerun_ldconfig = 0, rerun_cnt = 0;
34 char initpath[256];
36 #ifdef __i386__
37 char buffer[4096];
38 struct pref {
39 char *p;
40 int len;
41 } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
42 { "librt-", 6 }, { "libpthread-", 11 },
43 { "librtkaio-", 10 }, { "libthread_db-", 13 } };
44 int i, j, fd;
45 off_t base;
46 ssize_t ret;
47 #ifdef ARCH_386
48 const char *remove_dirs[] = { "/lib/i686", "/lib/tls" };
49 #else
50 const char *remove_dirs[] = { "/lib/tls/i686" };
51 #endif
52 for (j = 0; j < sizeof (remove_dirs) / sizeof (remove_dirs[0]); ++j)
54 size_t rmlen = strlen (remove_dirs[j]);
55 fd = open (remove_dirs[j], O_RDONLY);
56 if (fd >= 0
57 && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
58 >= (ssize_t) offsetof (struct dirent, d_name))
60 for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
62 struct dirent *d = (struct dirent *) (buffer + base);
64 for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
65 if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
67 char *p = d->d_name + prefix[i].len;
69 while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
70 if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
71 && p + 3 - d->d_name
72 < sizeof (initpath) - rmlen - 1)
74 memcpy (initpath, remove_dirs[j], rmlen);
75 initpath[rmlen] = '/';
76 strcpy (initpath + rmlen + 1, d->d_name);
77 unlink (initpath);
78 break;
81 base += d->d_reclen;
83 close (fd);
86 #endif
88 int ldsocfd = open (LD_SO_CONF, O_RDONLY);
89 struct stat ldsocst;
90 if (ldsocfd >= 0 && fstat (ldsocfd, &ldsocst) >= 0)
92 char p[ldsocst.st_size + 1];
93 if (read (ldsocfd, p, ldsocst.st_size) == ldsocst.st_size)
95 p[ldsocst.st_size] = '\0';
96 if (strstr (p, "include ld.so.conf.d/*.conf") == NULL)
98 close (ldsocfd);
99 ldsocfd = open (LD_SO_CONF, O_WRONLY | O_TRUNC);
100 if (ldsocfd >= 0)
102 size_t slen = strlen ("include ld.so.conf.d/*.conf\n");
103 if (write (ldsocfd, "include ld.so.conf.d/*.conf\n", slen)
104 != slen
105 || write (ldsocfd, p, ldsocst.st_size) != ldsocst.st_size)
106 _exit (109);
110 if (ldsocfd >= 0)
111 close (ldsocfd);
116 char linkbuf[64], *linkp;
117 int linklen;
119 /* If installing bi-arch glibc, rpm sometimes doesn't unpack all files
120 before running one of the lib's %post scriptlet. /sbin/ldconfig will
121 then be run by the other arch's %post. */
122 if (access ("/sbin/ldconfig", X_OK))
123 break;
125 verbose_exec (110, "/sbin/ldconfig", "/sbin/ldconfig");
127 rerun_ldconfig = 0;
128 #ifdef LIBTLS
129 linkp = linkbuf + strlen (LIBTLS);
130 linklen = readlink (LIBTLS "librt.so.1", linkp,
131 sizeof (linkbuf) - 1 - strlen (LIBTLS));
132 if (linklen == strlen ("librtkaio-2.3.X.so")
133 && memcmp (linkp, "librtkaio-2.3.", 14) == 0
134 && strchr ("23", linkp[14])
135 && memcmp (linkp + 15, ".so", 4) == 0)
137 memcpy (linkbuf, LIBTLS, strlen (LIBTLS));
138 unlink (linkbuf);
139 rerun_ldconfig = 1;
141 #endif
143 #ifdef __i386__
144 linkp = linkbuf + strlen ("/lib/i686/");
145 linklen = readlink ("/lib/i686/librt.so.1", linkp,
146 sizeof (linkbuf) - 1 - strlen ("/lib/i686/"));
147 if (linklen == strlen ("librtkaio-2.3.X.so")
148 && memcmp (linkp, "librtkaio-2.3.", 14) == 0
149 && strchr ("23", linkp[14])
150 && memcmp (linkp + 15, ".so", 4) == 0)
152 memcpy (linkbuf, "/lib/i686/", strlen ("/lib/i686/"));
153 unlink (linkbuf);
154 rerun_ldconfig = 1;
156 #endif
158 while (rerun_ldconfig && ++rerun_cnt < 2);
160 if (! utimes (GCONV_MODULES_DIR "/gconv-modules.cache", NULL))
162 #ifndef ICONVCONFIG
163 #define ICONVCONFIG "/usr/sbin/iconvconfig"
164 #endif
165 verbose_exec (113, ICONVCONFIG, "/usr/sbin/iconvconfig",
166 "-o", GCONV_MODULES_DIR"/gconv-modules.cache",
167 "--nostdlib", GCONV_MODULES_DIR);
170 /* Check if telinit is available and the init fifo as well. */
171 if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
172 _exit (0);
173 /* Check if we are not inside of some chroot, because we'd just
174 timeout and leave /etc/initrunlvl. */
175 if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
176 readlink ("/proc/1/root", initpath, 256) <= 0)
177 _exit (0);
179 if (check_elf ("/proc/1/exe"))
180 verbose_exec (116, "/sbin/telinit", "/sbin/telinit", "u");
182 /* Check if we can safely condrestart sshd. */
183 if (access ("/sbin/service", X_OK) == 0
184 && access ("/usr/sbin/sshd", X_OK) == 0
185 && access ("/bin/bash", X_OK) == 0)
187 if (check_elf ("/usr/sbin/sshd"))
188 verbose_exec (121, "/sbin/service", "/sbin/service", "sshd", "condrestart");
191 _exit(0);
194 int __libc_multiple_threads __attribute__((nocommon));
195 int __libc_enable_asynccancel (void) { return 0; }
196 void __libc_disable_asynccancel (int x) { }
197 void __libc_csu_init (void) { }
198 void __libc_csu_fini (void) { }
199 pid_t __fork (void) { return -1; }
200 char thr_buf[65536];
202 #ifndef __powerpc__
204 __libc_start_main (int (*main) (void), int argc, char **argv,
205 void (*init) (void), void (*fini) (void),
206 void (*rtld_fini) (void), void * stack_end)
207 #else
208 struct startup_info
210 void *sda_base;
211 int (*main) (int, char **, char **, void *);
212 int (*init) (int, char **, char **, void *);
213 void (*fini) (void);
217 __libc_start_main (int argc, char **ubp_av, char **ubp_ev,
218 void *auxvec, void (*rtld_fini) (void),
219 struct startup_info *stinfo,
220 char **stack_on_entry)
221 #endif
223 #if defined __ia64__ || defined __powerpc64__
224 register void *r13 __asm ("r13") = thr_buf + 32768;
225 __asm ("" : : "r" (r13));
226 #elif defined __sparc__
227 register void *g6 __asm ("g6") = thr_buf + 32768;
228 # ifdef __arch64__
229 __thread_self = thr_buf + 32768;
230 # else
231 register void *__thread_self __asm ("g7") = thr_buf + 32768;
232 # endif
233 __asm ("" : : "r" (g6), "r" (__thread_self));
234 #elif defined __s390__ && !defined __s390x__
235 __asm ("sar %%a0,%0" : : "d" (thr_buf + 32768));
236 #elif defined __s390x__
237 __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 32768) : "0");
238 #elif defined __powerpc__ && !defined __powerpc64__
239 register void *r2 __asm ("r2") = thr_buf + 32768;
240 __asm ("" : : "r" (r2));
241 #endif
242 main();
243 return 0;
246 void
247 vexec (int failcode, char *const path[])
249 pid_t pid;
250 int status, save_errno;
252 pid = vfork ();
253 if (pid == 0)
255 execv (path[0], path + 1);
256 save_errno = errno;
257 message (path);
258 says (" exec failed with errno ");
259 sayn (save_errno);
260 says ("\n");
261 _exit (failcode);
263 else if (pid < 0)
265 save_errno = errno;
266 message (path);
267 says (" fork failed with errno ");
268 sayn (save_errno);
269 says ("\n");
270 _exit (failcode + 1);
272 if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
274 message (path);
275 says (" child terminated abnormally\n");
276 _exit (failcode + 2);
278 if (WEXITSTATUS (status))
280 message (path);
281 says (" child exited with exit code ");
282 sayn (WEXITSTATUS (status));
283 says ("\n");
284 _exit (WEXITSTATUS (status));
288 void
289 says (const char *str)
291 write (1, str, strlen (str));
294 void
295 sayn (long num)
297 char string[sizeof (long) * 3 + 1];
298 char *p = string + sizeof (string) - 1;
300 *p = '\0';
301 if (num == 0)
302 *--p = '0';
303 else
304 while (num)
306 *--p = '0' + num % 10;
307 num = num / 10;
310 says (p);
313 void
314 message (char *const path[])
316 says ("/usr/sbin/glibc_post_upgrade: While trying to execute ");
317 says (path[0]);
321 check_elf (const char *name)
323 /* Play safe, if we can't open or read, assume it might be
324 ELF for the current arch. */
325 int ret = 1;
326 int fd = open (name, O_RDONLY);
327 if (fd >= 0)
329 Elf32_Ehdr ehdr;
330 if (read (fd, &ehdr, offsetof (Elf32_Ehdr, e_version))
331 == offsetof (Elf32_Ehdr, e_version))
333 ret = 0;
334 if (ehdr.e_ident[EI_CLASS]
335 == (sizeof (long) == 8 ? ELFCLASS64 : ELFCLASS32))
337 #if defined __i386__
338 ret = ehdr.e_machine == EM_386;
339 #elif defined __x86_64__
340 ret = ehdr.e_machine == EM_X86_64;
341 #elif defined __ia64__
342 ret = ehdr.e_machine == EM_IA_64;
343 #elif defined __powerpc64__
344 ret = ehdr.e_machine == EM_PPC64;
345 #elif defined __powerpc__
346 ret = ehdr.e_machine == EM_PPC;
347 #elif defined __s390__ || defined __s390x__
348 ret = ehdr.e_machine == EM_S390;
349 #elif defined __x86_64__
350 ret = ehdr.e_machine == EM_X86_64;
351 #elif defined __sparc__
352 if (sizeof (long) == 8)
353 ret = ehdr.e_machine == EM_SPARCV9;
354 else
355 ret = (ehdr.e_machine == EM_SPARC
356 || ehdr.e_machine == EM_SPARC32PLUS);
357 #else
358 ret = 1;
359 #endif
362 close (fd);
364 return ret;